www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]    作者:華清遠(yuǎn)見(jiàn)講師  近期需要把 Android4.4 KitKat 的 HDMI 高清輸出功能移植到 fs4412 開(kāi)發(fā)平臺(tái),查閱了相關(guān)資料,經(jīng)過(guò)一段時(shí)間的研究、調(diào)試,終于成功輸出 1080

  

  作者:華清遠(yuǎn)見(jiàn)講師

  近期需要把 Android4.4 KitKat 的 HDMI 高清輸出功能移植到 fs4412 開(kāi)發(fā)平臺(tái),查閱了相關(guān)資料,經(jīng)過(guò)一段時(shí)間的研究、調(diào)試,終于成功輸出 1080P 的圖像到電視,當(dāng)然也支持720P 的輸出了,這里筆者記錄移植過(guò)程及注意事項(xiàng),方便有相同需求的客戶作為技術(shù)參考。

  1.1.1 HDMI 基礎(chǔ)知識(shí)

  HDMI(High-DefinitionMultimedia Interface)又被稱為高清晰度多媒體接口,是首個(gè)支持在單線纜上傳輸,不經(jīng)過(guò)壓縮的全數(shù)字高清晰度、多聲道音頻和智能格式與控制命令數(shù)據(jù)的數(shù)字接口。HDMI 接口由 Silicon Image 美國(guó)晶像公司倡導(dǎo),聯(lián)合索尼、日立、松下、飛利浦、湯姆遜、東芝等八家著名的消費(fèi)類電子制造商聯(lián)合成立的工作組共同開(kāi)發(fā)的。

  1.1.2 HDMI 傳輸原理

  HDMI 采用 TMDS (TimeMinimized Differential Signal)最小化傳輸差分信號(hào)傳輸技術(shù), TMDS 是一種微分信號(hào)機(jī)制,采用的是差分傳動(dòng)方式 ,是一種利用 2 個(gè)引腳間電壓差來(lái)傳送信號(hào)的技術(shù)。每一個(gè)標(biāo)準(zhǔn)的 HDMI 連接,都包含了 3 個(gè)用于傳輸數(shù)據(jù)的 TMDS 傳輸通道,還有 1 個(gè)獨(dú)立的 TMDS 時(shí)鐘通道,以保證傳輸時(shí)所需的統(tǒng)一時(shí)序。在一個(gè)時(shí)鐘周期內(nèi),每個(gè) TMDS 通道都能傳送 10bit 的數(shù)據(jù)流。而這 10bit 數(shù)據(jù),可以由若干種不同的編碼格式構(gòu)成。

  所用到的術(shù)語(yǔ):

  HDMI 把視頻信號(hào)分為 R、G、B、H、V 五種信號(hào)用 TMDS 技術(shù)編碼。

  TMDS:這三個(gè)通道傳輸 R、G、B 三原色,HV 編碼在 B 信號(hào)通道里面?zhèn)鬏?R、G 的多余位置用來(lái)傳輸音頻信號(hào)。

  DDC :即顯示數(shù)據(jù)通道,用來(lái)向視頻接收裝置發(fā)送配置信息和數(shù)據(jù)格式信息,接收裝置讀取這些 E-EDID(增強(qiáng)擴(kuò)展顯示識(shí)別數(shù)據(jù))的信息。

  CEC:即消費(fèi)電子控制通道,通過(guò)這條通道可以控制視聽(tīng)設(shè)備的工作。

  1.1.3 HDMI 數(shù)據(jù)容量

  HDMI 電路中的時(shí)鐘頻率,在 1.0 版本規(guī)定為 25MHz-165MHz 之間,也就是說(shuō)一個(gè) TMDS通道每秒最多能傳輸 165MHz×10bit=1.65Gbit 的數(shù)據(jù),3 個(gè) TMDS 通道一秒就可以傳輸1.65×3=4.95Gbit 的數(shù)據(jù),再加上控制數(shù)據(jù),用標(biāo)準(zhǔn)方法表示就是 4.96Gbps 的帶寬;若傳輸信號(hào)的比率小于 25MHz,HDMI 會(huì)采用自動(dòng)循環(huán)技術(shù)填補(bǔ)碼率,將信號(hào)的碼率提升到 25MHz 的水平。

  如果用像素點(diǎn)來(lái)表示,那就是一秒可以傳輸顯示 1.65G 個(gè)像素點(diǎn)(一個(gè)完整的像素點(diǎn)信息由 R/G/B

  三原色信息構(gòu)成)所需要的數(shù)據(jù)量。

  在 1.3 版本規(guī)格中,TMDS 連接帶寬從原來(lái)最高 165MHz 提升到 340MHz,數(shù)據(jù)傳輸率也從 4.96Gbps 提升到了 10.2Gbps,可以支持支持更高數(shù)據(jù)量的高清數(shù)字流量,如果采用 Type B 型雙路 TMDS 連接,則可以在此基礎(chǔ)上再提升一倍系統(tǒng)帶寬。

  1.1.4 HDMI 數(shù)據(jù)傳輸

  HDMI 輸入的源編碼格式包括視頻像素?cái)?shù)據(jù)(8 位)、控制數(shù)據(jù)(2 位)和數(shù)據(jù)包(4 位)。其中數(shù)據(jù)包中包含有音頻數(shù)據(jù)和輔助信息數(shù)據(jù)。數(shù)據(jù)傳輸過(guò)程可以分成三個(gè)部分:視頻數(shù)據(jù)傳輸期、島嶼數(shù)據(jù)傳輸期和控制數(shù)據(jù)傳輸期。

  視頻數(shù)據(jù)傳輸期:HDMI 數(shù)據(jù)線上傳送視頻像素信號(hào),視頻信號(hào)經(jīng)過(guò)編碼,生成 3 路(即 3 個(gè)TMDS 數(shù)據(jù)信息通道,每路 8 位)共 24 位的視頻數(shù)據(jù)流,輸入到 HDMI 發(fā)射器中。24 位像素的視頻信號(hào)通過(guò) TMDS 通道傳輸,將每通道 8 位的信號(hào)編碼轉(zhuǎn)換為 10 位,在每個(gè) 10 位像素時(shí)鐘周期傳送一個(gè)最小化的信號(hào)序列,視頻信號(hào)被調(diào)制為 TMDS 數(shù)據(jù)信號(hào)傳送出去,最后到接受器中接收。

  1.1.5 HDMI 音頻功能

  傳統(tǒng)的數(shù)字音頻信號(hào)的傳輸主要依靠?jī)煞N途徑:同軸電纜和光纖傳輸。

  同軸電纜傳輸數(shù)字音頻信號(hào)是一種非常成熟且高質(zhì)量的方式。這種接口標(biāo)準(zhǔn)對(duì)設(shè)備端的硬件要求較低,但是在傳輸高頻信號(hào)時(shí),容易發(fā)生比較大的衰減,影響到最終音質(zhì)。

  光纖對(duì)設(shè)備接收、發(fā)射端的同步時(shí)許要求非常嚴(yán)格,在技術(shù)上比同軸要難于實(shí)現(xiàn),但是光纖技術(shù)在長(zhǎng)距離傳輸方面的優(yōu)勢(shì)非常明顯,不會(huì)出現(xiàn)同軸電纜長(zhǎng)距離衰減過(guò)大的問(wèn)題,因此也得到了很多有距離限制以及新裝修用戶的青睞。

  HDMI 技術(shù)則綜合了以上兩者的優(yōu)點(diǎn):物理層采用成熟的電纜連接。HDMI 理論上可以實(shí)現(xiàn)最高 20 米的無(wú)損耗數(shù)字音頻信號(hào)傳播,那些對(duì)距離有要求的用戶也能較好接受。

  1.1.6 HDMI 接口類型

  常見(jiàn)的 HDMI 類型有 A、B、C 三種類型。其中 A 型是標(biāo)準(zhǔn)的 19 針 HDMI 接口,普及率最高;B 型接口尺寸稍大,但是有 29 個(gè)引腳,可以提供雙 TMDS 傳輸通道。而 C 型接口和 A 型接口性能一致,但是體積較小,更加適合緊湊型便攜設(shè)備使用。接口 A、接口 B、接口 C

  注: fs4412開(kāi)發(fā)板HDMI采用的是TYPE C接口

  1.1.7 HDMI 特點(diǎn)

  1、更好的抗干擾性能,能實(shí)現(xiàn)最長(zhǎng) 20 米的無(wú)增益?zhèn)鬏敗?/p>

  2、針對(duì)大尺寸數(shù)字平板電視分辨率進(jìn)行優(yōu)化,兼容性好。

  3、支持 EDID 和 DDC2B 標(biāo)準(zhǔn),設(shè)備之間可以智能選擇最佳匹配的連接方式。

  4、擁有強(qiáng)大的版權(quán)保護(hù)機(jī)制(HDCP),有效防止盜版現(xiàn)象。

  5、支持 24bit 色深處理,(RGB、YCbCr4-4-4、YCbCr4-2-2)。

  6、接口體積小,各種設(shè)備都能輕松安裝。

  7、一根線纜實(shí)現(xiàn)數(shù)字音頻、視頻信號(hào)同步傳輸,有效降低使用成本和繁雜程度。

  8、完全兼容 DVI 接口標(biāo)準(zhǔn),用戶不用擔(dān)心新舊系統(tǒng)不匹配。

  9、支持熱插拔技術(shù)。

  移植環(huán)境:

  1 fs4412開(kāi)發(fā)平臺(tái)

  2 kernel 3.0.15 version

  3 Android4.4.4

  4 Ubuntu12.04 64BIt 開(kāi)發(fā)環(huán)境

  注:筆者移植過(guò)程中查詢了 HDMI 相關(guān)的一些技術(shù)資料,在此感謝 CSDN 博主對(duì) HDMI的基礎(chǔ)分析:http://blog.csdn.net/xubin341719/article/details/7713450,以上 HDMI 基本概念描述轉(zhuǎn)載自此博客。

  1.2 硬件相關(guān)部分 ---查找硬件原理圖

  下圖為 fs4412 開(kāi)發(fā)板底板 HDMI 接口引腳定義:

  

  原理圖結(jié)合 HDMI 接口定義標(biāo)準(zhǔn)我們可以獲知:

  1 TMDS_D0-、TMDS_D0+, TMDS_D1- 、TMDS_D1+, TMDS_D2- 、TMDS_D2+ 三對(duì)數(shù)據(jù)線用于傳輸視頻和音頻及控制信號(hào);

  2 TMDS_CLK+、TMDS_CLK-為 HDMI 傳輸提供時(shí)鐘源;

  3 SCL,SDA 為 I2C 控制信號(hào),用于 EDID 協(xié)議傳輸,主要用于板卡與 HDMI 顯示設(shè)備之間進(jìn)行協(xié)商,比如查詢 HDMI 顯示設(shè)備支持的最大分辨率,板卡設(shè)置 HDMI 輸出分辨率等等均通過(guò) I2C 總線傳輸,fs4412 開(kāi)發(fā)平臺(tái)采用 I2C0 傳輸 EDID。 I2C 作為 HDMI 的 DDC 通道,用于設(shè)備之間的溝通。

  4 HDMI_HPD 引腳用于產(chǎn)生熱插拔中斷信號(hào),CPU 端通過(guò)此信號(hào)可以知道有 HDMI 設(shè)備插入或者拔出,驅(qū)動(dòng)程序會(huì)處理中斷,告知到 Android 層。

  5 CEC引腳用于 HDMI 的高級(jí)客戶定制功能,用于傳輸廠商自定義的命令,屬于 HDMI 的拓展功能,比如 HDMI 發(fā)送端設(shè)備可以通過(guò) CEC 引腳告知 HDMI 顯示設(shè)備隨同發(fā)送設(shè)備開(kāi)機(jī),關(guān)機(jī)等操作。

  1.3 Kernel

  1.3.1 概述

  fs4412 開(kāi)發(fā)板采用的內(nèi)核是 Linux 3.0.15 版本,我們這邊沒(méi)有三星官方的關(guān)于 HDMI的 PortingGuid, 只能是自己根據(jù) Exynos4412 的 Datasheet 結(jié)合三星提供的內(nèi)核代碼進(jìn)行分析。

  我們先看一下 Exynos4412 Datasheet 中關(guān)于 HDMI 功能的屬性支持:

  The features of HDMI are:

  Complies with HDMI 1.4 (3D feature), HDCP 1.1, and DVI 1.0

  The video formats that HDMI supports are:

  480p 59.94 Hz/60 Hz, 576p @ 50 Hz

  720p @ 50 Hz/59.94 Hz/60 Hz

  1080i @ 50 Hz/59.94 Hz/60 Hz

  1080p @ 50 Hz/59.94 Hz/60 Hz

  Supports other various formats up to 148.5 MHz Pixel Clock

  Supports Color Format: 4:4:4 RGB/YCbCr

  Supports 8-bit precision per color only

  Supports CEC function

  Contains an Integrated HDCP Encryption Engine for video/ audio content protection

  Does not include DDC. There is a dedicated Inter-Integrated Circuit (I2C) for DDC in Exynos 4412 SCP

  可以知道 HDMI 控制器支持 HDMI1.4,HDCP1.1,DVI1.0 規(guī)范,另外支持最高 1080P 60HZ的顯示,當(dāng)然也支持最常見(jiàn)的 480P ,720P,1080i 輸出,另外 HDMI 輸出的顏色格式可是 RGB的也可以是 YUV 的,這個(gè)可以通過(guò)軟件界面進(jìn)行輸出設(shè)置。

  DDC 全文為 Display Data Channel,用于 HDMI 設(shè)備之間的協(xié)議溝通,Exynos4412 內(nèi)部沒(méi)有專用的 DDC 控制器,而是采用 I2C 總線完成這部分工作,驅(qū)動(dòng)部分使用 I2C 傳輸控制命令到顯示終端設(shè)備。

  系統(tǒng)框圖:

  HDMI 的視頻數(shù)據(jù)是通過(guò) MIXER 輸入到 HDMI CORE 核心,然后通過(guò) PHY 發(fā)送出去,MIXER 是視頻混合器,用于圖層的混合。音頻數(shù)據(jù)源有兩路,一路是 SPDIF 總線輸入,另外一路是 I2S 音頻總線輸入,我們的開(kāi)發(fā)板采用的是 I2S 的音頻源,故音頻輸入是通過(guò) I2S 傳輸?shù)紿DMI CORE 的。

  另外需要注意一下 HDMI PHY,Exynos4412 集成了 HDMI PHY,PHY 用于產(chǎn)生 pixel 時(shí)鐘和TMDS 時(shí)鐘,我們不再需要額外的 PHY 芯片,這樣可以省去 PCB 布線,當(dāng)然還有 cost,軟件通過(guò) CPU 內(nèi)部的專用的 I2C 總線配置 Phy 寄存器,針對(duì) Phy 進(jìn)行控制,比如開(kāi)啟,關(guān)閉 PHY電源等等。

  HDMI 功能在 Exynos4412 平臺(tái)中屬于 TVOUT 子系統(tǒng)的一部分,圖形圖像數(shù)據(jù)可以輸出到 TV顯示設(shè)備,也可以輸出到 HDMI 顯示設(shè)備 : 如圖,VideoProcessor 硬件模塊從內(nèi)存獲取到 YUV420 格式的圖像數(shù)據(jù)進(jìn)行裁剪,及空間色彩轉(zhuǎn)換,然后把數(shù)據(jù)傳輸?shù)?MIXER 硬件模塊,Dataheet 是這樣解釋 VideoProcessor 的功能定義:

  Video Processor (VP) is responsible for video scaling, de-interlacing, and video post processing of TV-out data path. VP reads reconstructed YCbCr 4:2:0 video sequences from DRAM. It then processes the sequence, and sends it to on-the- fly Mixer。

  MIXER 模塊主要是對(duì)VideoProcessor輸入的圖形,視頻,背景進(jìn)行混合疊加,形成完成的窗口顯示,然后把數(shù)據(jù)傳輸?shù)絋VENC進(jìn)行編碼,數(shù)模轉(zhuǎn)換,輸出到TV設(shè)備,或者把數(shù)據(jù)傳輸?shù)紿DMI模塊,由HDMI的PHY把數(shù)據(jù)傳輸?shù)紿DMI接收顯示設(shè)備。

  Mixer overlaps or blends the input data such as graphic, video, background and sends the resulting data to the TVOUT module. The TVOUT module generates all the video control signals

  如果您對(duì)MIXER的功能作用不是很清楚,可以看一下Datasheet中對(duì)MIXER混合器描述的圖例: 通過(guò)上面的解釋,我們知道內(nèi)存數(shù)據(jù)是如何顯示到HDMI設(shè)備上的,這樣對(duì)HDMI就有了一個(gè)框架性的認(rèn)識(shí)和理解,方便我們分析 Linux HDMI驅(qū)動(dòng)結(jié)構(gòu),及驅(qū)動(dòng)模塊在HDMI使用中扮演怎么樣的角色。

  1.3.2 內(nèi)核代碼

  這里我們把 HDMI 驅(qū)動(dòng)相關(guān)劃分為兩部分,一部分是驅(qū)動(dòng)文件,驅(qū)動(dòng)文件實(shí)現(xiàn)了HDMI 的驅(qū)動(dòng)架構(gòu)。另外一部分是板級(jí)支持文件,與 fs4412 開(kāi)發(fā)板相關(guān)的文件。

  1.3.2.1 驅(qū)動(dòng)文件

  首先我們看一下 HDMI 驅(qū)動(dòng)相關(guān)文件夾,因?yàn)?HDMI 屬于 TVOUT 子系統(tǒng)的一部分,那么HDMI 驅(qū)動(dòng)是離不開(kāi) TV 輸出系統(tǒng)的:

  路徑:drivers/media/video/Samsung/tvout

  TVOUT 文件夾為 TVOUT 子系統(tǒng)的驅(qū)動(dòng),HDMI 驅(qū)動(dòng)就位于其中:

  這里我們看到了 s5p_tvout_hpd.c 關(guān)于 HDMI 熱插拔事件相關(guān)驅(qū)動(dòng),該驅(qū)動(dòng)文件會(huì)產(chǎn)生/dev/HPD 設(shè)備節(jié)點(diǎn),用戶態(tài)軟件會(huì)打開(kāi)設(shè)備節(jié)點(diǎn),用于監(jiān)控 HDMI 設(shè)備的插入和拔出。 s5p_mixer_ctrl.c 視頻混合器,s5p_vp_ctrl.c 圖形裁剪驅(qū)動(dòng),這些文件是 TV 驅(qū)動(dòng)調(diào)用接口文件,實(shí)際的實(shí)現(xiàn)位于 hw_if 文件夾下面,hw_if 文件夾下面的這些文件會(huì)操作最底層的寄存器配置: 比如 hdmi.c 文件包含對(duì) HDMI 控制寄存器,狀態(tài)寄存器,及其他功能寄存器的配置,當(dāng)然也包含了對(duì) HDMI PHY 配置:

  void s5p_hdmi_reg_enable(bool en)

  {

  u8 reg;

  reg = readb(hdmi_base + S5P_HDMI_CON_0);

  if (en)

  reg |= S5P_HDMI_EN;

  else

  reg &= ~(S5P_HDMI_EN | S5P_HDMI_ASP_EN);

  writeb(reg, hdmi_base + S5P_HDMI_CON_0);

  if (!en) {

  do {

  reg = readb(hdmi_base + S5P_HDMI_CON_0);

  } while (reg & S5P_HDMI_EN);

  }

  }

  s32 s5p_hdmi_phy_config( enum phy_freq freq, enum s5p_hdmi_color_depth cd)

  {

  s32 index;

  s32 size;

  u8 buffer[32] = {0, };

  u8 reg;

  int loop =0;

  switch (cd) {

  case HDMI_CD_24:

  index = 0;

  break;

  case HDMI_CD_30:

  index = 1;

  break;

  case HDMI_CD_36:

  index = 2;

  break;

  default:

  return -1;

  }

  buffer[0] = PHY_REG_MODE_SET_DONE;

  buffer[1] = 0x00;

  if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buffer) != 0) {

  tvout_err("s5p_hdmi_i2c_phy_write failed.n");

  return -1;

  }

  writeb(0x5, i2c_hdmi_phy_base + HDMI_I2C_LC);

  size = sizeof(phy_config[freq][index])

  / sizeof(phy_config[freq][index][0]);

  memcpy(buffer, phy_config[freq][index], sizeof(buffer));

  if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, size, buffer) != 0)

  return -1;

  #ifdef CONFIG_HDMI_PHY_32N

  buffer[0] = PHY_REG_MODE_SET_DONE;

  buffer[1] = 0x80;

  if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buffer) != 0) {

  tvout_err("s5p_hdmi_i2c_phy_write failed.n");

  return -1;

  }

  #else

  buffer[0] = 0x01;

  if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) {

  tvout_err("s5p_hdmi_i2c_phy_write failed.n");

  return -1;

  }

  #endif

  s5p_hdmi_print_phy_config();

  #ifndef CONFIG_HDMI_PHY_32N

  s5p_hdmi_reg_core_reset();

  #endif

  #ifdef CONFIG_HDMI_PHY_32N

  do {

  reg = readb(hdmi_base + S5P_HDMI_PHY_STATUS0);

  } while (!(reg & S5P_HDMI_PHY_STATUS_READY));

  #else

  do {

  reg = readb(hdmi_base + S5P_HDMI_PHY_STATUS);

  mdelay(5);

  loop++;

  if(loop==100) return -1; //added yqf, for robust

  } while (!(reg & S5P_HDMI_PHY_STATUS_READY));

  #endif

  writeb(I2C_CLK_PEND_INT, i2c_hdmi_phy_base + HDMI_I2C_CON);

  writeb(I2C_IDLE, i2c_hdmi_phy_base + HDMI_I2C_STAT);

  return 0;

  }

  Mixer.c 文件包含了對(duì)視頻混合器的底層配置:

  void s5p_mixer_start(void)

  {

  writel((readl(mixer_base + S5P_MXR_STATUS) | S5P_MXR_STATUS_RUN),

  mixer_base + S5P_MXR_STATUS);

  }

  void s5p_mixer_stop(void)

  {

  u32 reg = readl(mixer_base + S5P_MXR_STATUS);

  reg &= ~S5P_MXR_STATUS_RUN;

  writel(reg, mixer_base + S5P_MXR_STATUS);

  do {

  reg = readl(mixer_base + S5P_MXR_STATUS);

  } while (!(reg & S5P_MXR_STATUS_IDLE_MODE));

  }

  這些驅(qū)動(dòng)文件中當(dāng)然有一個(gè)主文件,作為驅(qū)動(dòng)的入口文件,他就是 s5p_tvout.c 文件, 該文件提供了驅(qū)動(dòng)注冊(cè)函數(shù),另外構(gòu)建了 VideoProcessor 對(duì)象,MIXER 視頻混淆器對(duì)象還有非常重要的 V4L2 用戶態(tài)調(diào)用接口,用戶態(tài)程序是通過(guò) V4L2 接口控制 HDMI 的輸出的。

  static int __devinit s5p_tvout_probe(struct platform_device *pdev)

  {

  s5p_tvout_pm_runtime_enable(&pdev->dev);

  #if defined(CONFIG_S5P_SYSMMU_TV) && defined(CONFIG_VCM)

  if (s5p_tvout_vcm_create_unified() < 0)

  goto err;

  if (s5p_tvout_vcm_init() < 0)

  goto err;

  #elif defined(CONFIG_S5P_SYSMMU_TV) && defined(CONFIG_S5P_VMEM)

  s5p_sysmmu_enable(&pdev->dev);

  printk("sysmmu onn");

  s5p_sysmmu_set_tablebase_pgd(&pdev->dev, __pa(swapper_pg_dir));

  #endif

  #ifndef CONFIG_TC4_EVT //yqf

  tv_regulator_vdd18 = regulator_get(NULL, "vdd18_mipi");

  if (IS_ERR(tv_regulator_vdd18)) {

  printk("%s: failed to get %sn", __func__, "vdd18_mipi");

  goto err_regulator;

  }

  //regulator_enable(tv_regulator_vdd18);

  tv_regulator_vdd10 = regulator_get(NULL, "vdd10_mipi");

  if (IS_ERR(tv_regulator_vdd10)) {

  printk("%s: failed to get %sn", __func__, "vdd10_mipi");

  goto err_regulator;

  }

  //regulator_enable(tv_regulator_vdd10);

  #endif

  if (s5p_tvout_clk_get(pdev, &s5ptv_status) < 0)

  goto err;

  if (s5p_vp_ctrl_constructor(pdev) < 0)

  goto err;

  /* s5p_mixer_ctrl_constructor must be called

  before s5p_tvif_ctrl_constructor */

  if (s5p_mixer_ctrl_constructor(pdev) < 0)

  goto err;

  if (s5p_tvif_ctrl_constructor(pdev) < 0)

  goto err;

  if (s5p_tvout_v4l2_constructor(pdev) < 0)

  goto err;

  #ifdef CONFIG_HAS_EARLYSUSPEND

  spin_lock_init(&s5ptv_status.tvout_lock);

  s5ptv_early_suspend.suspend = s5p_tvout_early_suspend;

  s5ptv_early_suspend.resume = s5p_tvout_late_resume;

  s5ptv_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; //added yqf, suspend

  before LCD

  register_early_suspend(&s5ptv_early_suspend);

  suspend_status = 0;

  #endif

  #ifdef CONFIG_TV_FB

  #ifndef CONFIG_USER_ALLOC_TVOUT

  clk_enable(s5ptv_status.i2c_phy_clk); //added yqf

  s5p_hdmi_phy_power(true);

  if (s5p_tvif_ctrl_start(TVOUT_720P_60, TVOUT_HDMI) < 0) //yqf, back later

  goto err;

  #endif

  /* prepare memory */

  if (s5p_tvout_fb_alloc_framebuffer(&pdev->dev))

  goto err;

  if (s5p_tvout_fb_register_framebuffer(&pdev->dev))

  goto err;

  #endif

  on_stop_process = false;

  on_start_process = false;

  return 0;

  #ifndef CONFIG_TC4_EVT

  err_regulator:

  regulator_put(tv_regulator_vdd18);

  regulator_put(tv_regulator_vdd10);

  #endif

  err:

  return -ENODEV;

  }

  static const struct dev_pm_ops s5p_tvout_pm_ops = {

  .suspend = s5p_tvout_suspend,

  .resume = s5p_tvout_resume,

  .runtime_suspend = s5p_tvout_runtime_suspend,

  .runtime_resume = s5p_tvout_runtime_resume

  };

  static struct platform_driver s5p_tvout_driver = {

  .probe = s5p_tvout_probe,

  .remove = s5p_tvout_remove,

  .driver = {

  .name = "s5p-tvout",

  .owner = THIS_MODULE,

  .pm = &s5p_tvout_pm_ops

  },

  };

  static char banner[] __initdata =

  KERN_INFO "S5P TVOUT Driver v3.0 (c) 2010 Samsung Electronicsn";

  static int __init s5p_tvout_init(void)

  {

  int ret;

  printk(banner);

  ret = platform_driver_register(&s5p_tvout_driver);

  if (ret) {

  printk(KERN_ERR "Platform Device Register Failed %dn", ret);

  return -1;

  }

  #ifdef CONFIG_PM

  tvout_resume_wq = create_freezable_workqueue("tvout resume work");

  if (!tvout_resume_wq) {

  printk(KERN_ERR "Platform Device Register Failed %dn", ret);

  platform_driver_unregister(&s5p_tvout_driver);

  return -1;

  }

  INIT_WORK(&tvout_resume_work, (work_func_t) s5p_tvout_resume_work);

  #endif

  return 0;

  }

  static void __exit s5p_tvout_exit(void)

  {

  #ifdef CONFIG_HAS_EARLYSUSPEND

  mutex_destroy(&s5p_tvout_mutex);

  #endif

  platform_driver_unregister(&s5p_tvout_driver);

  }

  late_initcall(s5p_tvout_init);

  module_exit(s5p_tvout_exit);

  1.3.2.2 板級(jí)相關(guān)文件

  文件列表:

  arch/arm/mach-exynos/mach-fs4412.c

  arch/arm/plat-s5p/dev-tvout.c

  arch/arm/mach-exynos/setup-tvout.c

  mach-fs4412.c 文件為 fs4412 開(kāi)發(fā)板的入口文件,該文件定義了 fs4412 開(kāi)發(fā)板的所有板載資源,當(dāng)然也包括 HDMI 相關(guān)的設(shè)備:

  static struct platform_device *smdk4x12_devices[] __initdata = {

  …...

  #ifdef CONFIG_VIDEO_TVOUT

  &s5p_device_tvout,

  &s5p_device_cec,

  &s5p_device_hpd,

  #endif

  ……..

  }

  static void __init smdk4x12_machine_init(void)

  {

  ……

  #if defined(CONFIG_VIDEO_TVOUT)

  s5p_hdmi_hpd_set_platdata(&hdmi_hpd_data);

  s5p_hdmi_cec_set_platdata(&hdmi_cec_data);

  #ifdef CONFIG_EXYNOS_DEV_PD

  s5p_device_tvout.dev.parent = &exynos4_device_pd[PD_TV].dev;

  exynos4_device_pd[PD_TV].dev.parent= &exynos4_device_pd[PD_LCD0].dev;

  #endif

  …….

  }

  dev-tvout.c 文件定義了 HDMI 系統(tǒng)相關(guān)的設(shè)備,如 VideoProcess,Mixer 視頻混淆器占

  用的系統(tǒng)資源,如寄存器地址,中斷:

  /* TVOUT interface */

  static struct resource s5p_tvout_resources[] = {

  [0] = {

  .start = S5P_PA_TVENC,

  .end = S5P_PA_TVENC + S5P_SZ_TVENC - 1,

  .flags = IORESOURCE_MEM,

  .name = "s5p-sdo"

  },

  [1] = {

  .start = S5P_PA_VP,

  .end = S5P_PA_VP + S5P_SZ_VP - 1,

  .flags = IORESOURCE_MEM,

  .name = "s5p-vp"

  },

  [2] = {

  .start = S5P_PA_MIXER,

  .end = S5P_PA_MIXER + S5P_SZ_MIXER - 1,

  .flags = IORESOURCE_MEM,

  .name = "s5p-mixer"

  },

  [3] = {

  .start = S5P_PA_HDMI,

  .end = S5P_PA_HDMI + S5P_SZ_HDMI - 1,

  .flags = IORESOURCE_MEM,

  .name = "s5p-hdmi"

  },

  [4] = {

  .start = S5P_I2C_HDMI_PHY,

  .end = S5P_I2C_HDMI_PHY + S5P_I2C_HDMI_SZ_PHY - 1,

  .flags = IORESOURCE_MEM,

  .name = "s5p-i2c-hdmi-phy"

  },

  [5] = {

  .start = IRQ_MIXER,

  .end = IRQ_MIXER,

  .flags = IORESOURCE_IRQ,

  .name = "s5p-mixer"

  },

  [6] = {

  .start = IRQ_HDMI,

  .end = IRQ_HDMI,

  .flags = IORESOURCE_IRQ,

  .name = "s5p-hdmi"

  },

  [7] = {

  .start = IRQ_TVENC,

  .end = IRQ_TVENC,

  .flags = IORESOURCE_IRQ,

  .name = "s5p-sdo"

  },

  };

  struct platform_device s5p_device_tvout = {

  .name = "s5p-tvout",

  .id = -1,

  .num_resources = ARRAY_SIZE(s5p_tvout_resources),

  .resource = s5p_tvout_resources,

  };

  EXPORT_SYMBOL(s5p_device_tvout);

  當(dāng)然也包括設(shè)備節(jié)點(diǎn) /dev/HPD 所使用的資源:

  /* HPD */

  static struct resource s5p_hpd_resources[] = {

  [0] = {

  .start = IRQ_TVOUT_HPD,

  .end = IRQ_TVOUT_HPD,

  .flags = IORESOURCE_IRQ,

  },

  };

  struct platform_device s5p_device_hpd = {

  .name = "s5p-tvout-hpd",

  .id = -1,

  .num_resources = ARRAY_SIZE(s5p_hpd_resources),

  .resource = s5p_hpd_resources,

  };

  EXPORT_SYMBOL(s5p_device_hpd);

  ■ setup-tvout.c 文件主要提供了 GPIO 引腳功能配置:

  void s5p_int_src_hdmi_hpd(struct platform_device *pdev)

  {

  s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0x3));

  s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_DOWN);

  }

  void s5p_int_src_ext_hpd(struct platform_device *pdev)

  {

  s3c_gpio_cfgpin(EXYNOS4_GPX3(7), S3C_GPIO_SFN(0xf));

  s3c_gpio_setpull(EXYNOS4_GPX3(7), S3C_GPIO_PULL_DOWN);

  }

  int s5p_hpd_read_gpio(struct platform_device *pdev)

  {

  return gpio_get_value(EXYNOS4_GPX3(7));

  }

  void s5p_cec_cfg_gpio(struct platform_device *pdev)

  {

  s3c_gpio_cfgpin(EXYNOS4_GPX3(6), S3C_GPIO_SFN(0x3));

  s3c_gpio_setpull(EXYNOS4_GPX3(6), S3C_GPIO_PULL_NONE);

  }

  setup-tvout.c 文件提供的功能函數(shù)會(huì)被其他文件的函數(shù)體調(diào)用。

  1.3.2.3 內(nèi)核配置

  我們以 POP 核心的內(nèi)核配置為例來(lái)說(shuō)明:

  cp config_for_android_pop .config

  make menuconfig->Device Drivers->Multimedia support->video capture adapters

  Samsung TVOUT Driver使能該驅(qū)動(dòng)選項(xiàng),然后同樣打開(kāi) HDMI CEC ,HDMIHPD,HDMI

  14A Driver, HDMI PHY, TVOUT frame buffer driver support, Support pre allocate frame

  buffer memory.

  如果需要獲得更多的調(diào)試信息,需要使能 TVOUT driver debug message, 這樣內(nèi)核會(huì)輸出 HDMI 的調(diào)試信息到調(diào)試串口,為我們學(xué)習(xí) HDMI 驅(qū)動(dòng)提供有力的幫助,HDMI 功能調(diào)試完成后需要關(guān)閉該選項(xiàng),因?yàn)轭l繁的打印調(diào)試信息會(huì)影響到系統(tǒng)的性能,嚴(yán)重的情況下會(huì)導(dǎo)致 HDMI 輸出界面出現(xiàn)卡頓的現(xiàn)象。

  1.4 Android 空間

  Android4.4 系統(tǒng)是支持 HDMI 輸出顯示的,主要體現(xiàn) Androd 框架層的支持,及用戶設(shè)置界面關(guān)于 HDMI 參數(shù)設(shè)置。

  下面我們看一下 Android 的圖形顯示系統(tǒng)框架:

  HDMI 的輸出是由 SurfaceFlinger 控制 Mali Display(HW Composer)輸出的,我們會(huì)從HDMI HAL 層代碼看到 HW Composer 硬件合成器輸出圖像到 HDMI 顯示設(shè)備,硬件合成器是Honeycomb(android 發(fā)布版本)引入的一個(gè) HAL,SurfaceFlinger 使用它,利用硬件資源來(lái)加速 Surface 的合成,比如 3D GPU 和 2D 的圖形引擎。 Android 的 Framwork 層已經(jīng)支持 HDMI 的輸出顯示,我們重點(diǎn)關(guān)注的是 HDMI HAL 層的實(shí)現(xiàn)代碼,這也是我們 Porting 工作最重要的部分。

  1.4.1 HAL 層移植

  首先我們看一下 HDMI HAL 層相關(guān)文件夾:

  hardware/samsung_slsi/exynos4/libhdmi

  hardware/samsung_slsi/exynos4/libhwc

  libhdmi 文件夾是我們重點(diǎn)關(guān)注的對(duì)象,里面共有三個(gè)子文件夾:

  hardware/samsung_slsi/exynos4/libhdmi/ libhdmiservice

  hardware/samsung_slsi/exynos4/libhdmi/ libsForhdmi

  hardware/samsung_slsi/exynos4/libhdmi/ SecHdmi

  libhdmiservice: 該文件夾會(huì)編譯形成 libTVOut.so, libhdmiclient.so 庫(kù)文件。

  libhdmiservice 文件夾提供了 SecHdmiClient 類的實(shí)現(xiàn),及 SecHdmiClient 類對(duì)象的創(chuàng)建函數(shù)SecHdmiClient::getInstance(),硬件合成器 libhwc 會(huì)調(diào)用 SecHdmiClient::getInstance()函數(shù)創(chuàng)建全局唯一的 SecHdmiClient 對(duì)象,使用對(duì)象指針 mHdmiClient 指向該對(duì)象。

  libhwc 文件夾的關(guān)鍵文件 hwc.cpp,也是硬件合成器 libhwc 的 HAL 層文件,該文件會(huì)通過(guò)對(duì)象指針調(diào)用 SecHdmiClient 的接口函數(shù),比如使能 HDMI,設(shè)置 HDMI 的分辨率等等:

  hwc.cpp 調(diào)用 SecHdmiClient 類接口函數(shù)的相關(guān)代碼片段:

  #if defined(BOARD_USES_HDMI)

  android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();

  if (skip_hdmi_rendering == 1)

  return 0;

  if (contents == NULL) {

  // Don't display unnecessary image

  mHdmiClient->setHdmiEnable(0);

  return 0;

  } else {

  mHdmiClient->setHdmiEnable(1);

  }

  #ifdef SUPPORT_AUTO_UI_ROTATE

  #if 0 //yqf, move to FramebufferNativeWindow

  cur = &list->hwLayers[0];

  //LOGE("%s, cur->tran:%d n",__func__,cur->transform); //added yqf

  if (cur->transform == HAL_TRANSFORM_ROT_90 )//added yqf for test

  mHdmiClient->setHdmiRotate(90, ctx->num_of_hwc_layer);

  else if(cur->transform == HAL_TRANSFORM_ROT_270)

  mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);

  else if(cur->transform == HAL_TRANSFORM_ROT_180)

  mHdmiClient->setHdmiRotate(180, ctx->num_of_hwc_layer);

  else /*if(cur->transform == HAL_TRANSFORM_ROT_0)*/

  mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);

  #endif

  #endif

  libhdmi 文件夾里面包含了三個(gè)字文件夾 libcec,libddc,libedid,通過(guò)名字我們也就知道這個(gè)文件夾負(fù)責(zé)與 HDMI 顯示設(shè)備進(jìn)行 I2C 通信,查詢 HDMI 顯示設(shè)備的顯示能力,設(shè)置 HDMI顯示設(shè)備的分辨率。

  EDID: Extended display identification data,簡(jiǎn)稱 EDID,是指屏幕分辨率的信息,包括廠商名稱與序號(hào)。一般 EDID 存在于顯示器的 PROM 或 EEPROM 內(nèi)。一般如要讀取 EDID 都是透過(guò)I2C,slave address 是 0x50。

  EDID 的獲取是通過(guò) DDC 進(jìn)行的,DDC 就是開(kāi)發(fā)板與 HDMI 顯示設(shè)備之間進(jìn)行通信的通道,HDMI 發(fā)送端設(shè)備會(huì)通過(guò) DDC 讀取顯示器的 EDID 信息,然后根據(jù) EDID 信息判斷顯示能力等

  顯示參數(shù)。

  查看開(kāi)發(fā)板的硬件原理圖,我們可以知道 HDMI 使用 I2C0 與顯示設(shè)備通信,這里我們需

  要正確設(shè)置 I2C 通道:

  #define DEV_NAME "/dev/i2c-0"

  int DDCOpen()

  {

  int ret = 1;

  // check already open??

  if (ref_cnt > 0) {

  ref_cnt++;

  return 1;

  }

  // open

  if ((ddc_fd = open(DEV_NAME,O_RDWR)) < 0) {

  LOGE("%s: Cannot open I2C_DDC : %s",__func__, DEV_NAME);

  ret = 0;

  }

  ref_cnt++;

  return ret;

  }

  HDMI 的 CEC 屬于 HDMI 的擴(kuò)展功能,我們沒(méi)有使用到,這里不再解釋。

  SecHdmi 文件夾提供最底層的 V4L2 的調(diào)用。

  HDMI 的設(shè)備操作是通過(guò) Kernel HDMI 驅(qū)動(dòng)提供的設(shè)備節(jié)點(diǎn)來(lái)進(jìn)行的,HDMI 相關(guān)的設(shè)備

  節(jié)點(diǎn)有:

  /dev/video16 Graphics0 層設(shè)備節(jié)點(diǎn)

  /dev/video17 Graphics1 層設(shè)備節(jié)點(diǎn)

  /dev/video20 Video 層設(shè)備節(jié)點(diǎn)

  /dev/graphics/fb0 frambuffer 設(shè)備節(jié)點(diǎn)

  /dev/HPD HDMI 熱插拔檢測(cè)設(shè)備節(jié)點(diǎn)

  SecHdmi 文件夾實(shí)現(xiàn)這些設(shè)備節(jié)點(diǎn)的打開(kāi),控制,關(guān)閉操作。

  SecHdmi 文件夾對(duì)外提供 SecHdmi 類對(duì)象調(diào)用接口,libhdmiservice 文件夾會(huì)調(diào)用該對(duì)象的接口函數(shù),用于底層設(shè)備節(jié)點(diǎn)的控制。

  SecHdmi 文件夾也用于調(diào)用 libsForhdmi 文件夾通過(guò)的 EDID 接口,來(lái)獲取 HDMI 顯示設(shè)備的顯示能力,及設(shè)置顯示設(shè)備的分辨率。

  libhwc 模塊及 libhdmi 子模塊調(diào)用關(guān)系:

  另外 Android4.4 提供了 libhdmiservice_jni.so 庫(kù)文件,該庫(kù)文件提供了 Java 界面 HDMI參數(shù)設(shè)置的接口實(shí)現(xiàn),libhdmiservice_jni.so 文件最后也會(huì)調(diào)用到 libsForhdmi 層用于控制HDMI 顯示設(shè)備參數(shù)。

  1.4.2 HDMI 參數(shù)設(shè)置:

  Android4.4 Setting 界面可以控制 HDMI 輸出參數(shù):

  

  1.4.3 HDMI 編譯選項(xiàng)

  如果需要 Android4.4 編譯生成的鏡像支持 HDMI 顯示,那么編譯 Android 源代碼前必須

  配置好 HDMI 相關(guān)的宏定義:

  配置文件: device/samsung/smdk4x12/BoardConfig.mk

  添加以下宏定義:

  BOARD_USES_HDMI_SUBTITLES := true

  BOARD_USES_HDMI := true

  BOARD_HDMI_STD := STD_720P

  BOARD_HDMI_DDC_CH := DDC_CH_I2C_0

  BOARD_USES_FIMGAPI := true

  BOARD_USES_HDMI_EDID := true

  BOARD_USES_HDMI_JUMPER := false

  這樣我們的 Android4.4 即可支持 HDMI 顯示,且默認(rèn)輸出 720P 分辨率,DDC 采用 I2C0

  進(jìn)行通信,支持 HDMI 顯示設(shè)備 EDID 信息的獲取與配置。

  1.5 總結(jié)

  以上作為 fs4412 開(kāi)發(fā)平臺(tái)移植 HDMI 功能的過(guò)程總結(jié),Android4.4版本的 Kernel 及 Android 層代碼均包含 Porting 后的代碼,也就是 HDMI 正常工作的代碼,方便大家學(xué)習(xí)和產(chǎn)品研發(fā).

  HDMI 功能支持音視頻同步輸出,這里我們重點(diǎn)講解的是 HDMI 的 Porting 工作,如果對(duì)音視頻同步輸出有研究的朋友,可以自己閱讀相關(guān)的代碼,fs4412 開(kāi)發(fā)板的 HDMI 是支持1080P,720P 分辨率,同樣支持音視頻同步輸出。

  如果您在實(shí)際的項(xiàng)目中需要 HDMI 功能,請(qǐng)參考我們的原理圖設(shè)計(jì)硬件,盡量使用相同的 HDMI 資源,這樣您只需要關(guān)注硬件部分,驅(qū)動(dòng)使用我們移植好的即可,否則需要您修改HDMI 相關(guān)引腳配置,進(jìn)行必要的調(diào)試工作,增加自己的工作量。、


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉