scale_core.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. #include <linux/kernel.h>
  2. #include <linux/string.h>
  3. #include <linux/delay.h>
  4. #include <linux/interrupt.h>
  5. #include <linux/cdev.h>
  6. #include <linux/device.h>
  7. #include <linux/sched.h>
  8. #include <linux/fs.h>
  9. #include <linux/io.h>
  10. #include "scale.h"
  11. #define SYS_SOFT_RSTNB 0x78
  12. static unsigned char ver_cof[16][7]={
  13. {4,242, 22, 104, 22, 242, 4},//{4,-14, 22, 104, 22, -14, 4},
  14. {1, 243, 33, 86, 33, 243, 1},//{1, -13, 33, 86, 33, -13, 1},
  15. {251, 1, 36, 64, 36, 1, 251},//{-5, 1, 36, 64, 36, 1, -5},
  16. {252, 9, 34, 50, 34, 9, 252},//{-4, 9, 34, 50, 34, 9, -4},
  17. {255, 12, 32, 42, 32, 12,255},//{-1, 12, 32, 42, 32, 12, -1},
  18. {2, 13, 30, 38, 30, 13, 2},
  19. {5, 14, 28, 34, 28, 14, 5},
  20. {6, 16, 26, 32, 26, 16, 6},
  21. {9, 15, 25, 30, 25, 15, 9},
  22. {9, 15, 25, 30, 25, 15, 9},
  23. {11, 15, 24, 28, 24, 15, 11},
  24. {11, 15, 24, 28, 24, 15, 11},
  25. {12, 16, 23, 26, 23, 16, 12},
  26. {12, 16, 23, 26, 23, 16, 12},
  27. {13, 15, 23, 26, 23, 15, 13},
  28. {13, 16, 22, 26, 22, 16, 13}
  29. };
  30. static int get_scaler_cof(int iwin_height, int oheight)
  31. {
  32. int index;
  33. #if 0
  34. int val;
  35. float scaler_cof[] ={1.25, 1.50, 2.00, 2.50, 3.00, 3.50,
  36. 4.00, 4.50, 5.00, 5.50, 6.00, 6.50,
  37. 7.00, 7.50, 8.00, 8.50};
  38. val = iwin_height /(oheight + 4);
  39. #else
  40. long long val;
  41. int scaler_cof[] ={12500, 15000, 20000, 25000, 30000, 35000,
  42. 40000, 45000, 50000, 55000, 60000, 65000,
  43. 70000, 75000, 80000, 85000};
  44. val = iwin_height *10000 /(oheight + 4);
  45. #endif
  46. if(val >= scaler_cof[0] && val < scaler_cof[1])
  47. index = 0;
  48. else if(val >= scaler_cof[1] && val < scaler_cof[2])
  49. index = 1;
  50. else if(val >= scaler_cof[2] && val < scaler_cof[3])
  51. index = 2;
  52. else if(val >= scaler_cof[3] && val < scaler_cof[4])
  53. index = 3;
  54. else if(val >= scaler_cof[4] && val < scaler_cof[5])
  55. index = 4;
  56. else if(val >= scaler_cof[5] && val < scaler_cof[6])
  57. index = 5;
  58. else if(val >= scaler_cof[6] && val < scaler_cof[7])
  59. index = 6;
  60. else if(val >= scaler_cof[7] && val < scaler_cof[8])
  61. index = 7;
  62. else if(val >= scaler_cof[8] && val < scaler_cof[9])
  63. index = 8;
  64. else if(val >= scaler_cof[9] && val < scaler_cof[10])
  65. index = 9;
  66. else if(val >= scaler_cof[10] && val < scaler_cof[11])
  67. index = 10;
  68. else if(val >= scaler_cof[11] && val < scaler_cof[12])
  69. index = 11;
  70. else if(val >= scaler_cof[12] && val < scaler_cof[13])
  71. index = 12;
  72. else if(val >= scaler_cof[13] && val < scaler_cof[14])
  73. index = 13;
  74. else if(val >= scaler_cof[14] && val < scaler_cof[15])
  75. index = 14;
  76. else if(val >= scaler_cof[15] && val < scaler_cof[16])
  77. index = 15;
  78. else
  79. index = 16;
  80. return 16;
  81. }
  82. static void scale_rotate(struct ark_scale_context *context, int mode, int rotate, int pic_width, int pic_height, int pic_addr)
  83. {
  84. unsigned int roty_width =0,roty_src_width=0,rotc_width =0,rotc_src_width =0;
  85. unsigned int nor_act_width,nor_tot_width;
  86. int yuv420 = 0;
  87. unsigned int val;
  88. if((mode != SCALE_FORMAT_YUV420) && (mode != SCALE_FORMAT_YUV422)) {
  89. printk("%s, Invalid mode\n", __FUNCTION__);
  90. return ;
  91. }
  92. if(mode == SCALE_FORMAT_YUV420)
  93. yuv420 = 1;
  94. switch(rotate) {
  95. case SCALE_ROTATE_0: {
  96. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  97. val &=~(0x7f<<11);
  98. val |=(yuv420<<15)|(1<<11);
  99. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  100. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  101. val &=~(0xffffff);
  102. val |=(pic_height<<12)|pic_width;
  103. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  104. writel(0, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  105. if(pic_width%8 != 0) {
  106. nor_act_width = (pic_width/8+1)*8;
  107. } else {
  108. nor_act_width = pic_width;
  109. }
  110. if(pic_width%8 != 0) {
  111. nor_tot_width = (pic_width/8+1)*8;
  112. } else {
  113. nor_tot_width = pic_width;
  114. }
  115. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  116. val |=(nor_act_width<<12)|(nor_tot_width);
  117. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  118. writel(pic_addr, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  119. writel(pic_addr + pic_width*pic_height, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  120. break;
  121. }
  122. case SCALE_ROTATE_90: {
  123. if(pic_width%8 != 0){
  124. pic_width = (pic_width/8+1)*8;
  125. }
  126. if(yuv420) {
  127. if(pic_height%8 != 0){
  128. pic_height = (pic_height/8+1)*8;
  129. }
  130. }
  131. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  132. val &=~(0x7f<<11);
  133. val |=(1<<17)|(yuv420<<15)|(1<<14)|(1<<11);
  134. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  135. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  136. val &=~(0xffffff);
  137. val |=(pic_height<<12)|pic_width;
  138. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  139. writel(0, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  140. if(!yuv420) { //for yuv422 mode.
  141. if(pic_width%8 != 0)
  142. nor_act_width = (pic_width/8+1)*8;
  143. else
  144. nor_act_width = pic_width;
  145. if(pic_width%8 != 0)
  146. nor_tot_width = (pic_width/8+1)*8;
  147. else
  148. nor_tot_width = pic_width;
  149. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  150. val |=(0x1<<28)|(0x1<<26)|(0x1<<24)|(nor_act_width<<12)|(nor_tot_width);
  151. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  152. }
  153. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  154. val |=(0x1<<28)|(0x1<<26)|(0x1<<24);
  155. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  156. if(pic_height%8 != 0) {
  157. roty_width = (pic_height/8+1)*8;
  158. } else {
  159. roty_width = pic_height;
  160. }
  161. if(pic_width%8 != 0) {
  162. roty_src_width = (pic_width/8+1)*8;
  163. }
  164. else {
  165. roty_src_width = pic_width;
  166. }
  167. writel((roty_src_width<<12) | (roty_width<<0), context->mmio_base + AXI_SCALE_ROTYX_WIDTH);
  168. if(pic_height%8 != 0) {
  169. rotc_width = (pic_height/8+1)*8;
  170. }
  171. else {
  172. rotc_width = pic_height;
  173. }
  174. if(yuv420) {
  175. if(pic_width%16 != 0) {
  176. rotc_src_width = (pic_width/16+1)*8;
  177. } else {
  178. rotc_src_width = pic_width/2;
  179. }
  180. } else {
  181. if(pic_width%8 != 0)
  182. rotc_src_width = (pic_width/8+1)*8;
  183. else
  184. rotc_src_width = pic_width;
  185. }
  186. writel((rotc_src_width<<12)|(rotc_width<<0), context->mmio_base + AXI_SCALE_ROTCX_FADR);
  187. writel(pic_addr + roty_width-16, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  188. writel(pic_addr + roty_width*roty_src_width+rotc_width-16, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  189. break;
  190. }
  191. case SCALE_ROTATE_180: {
  192. if(pic_width%8 != 0) {
  193. pic_width = (pic_width/8+1)*8;
  194. }
  195. if(pic_height%8 != 0) {
  196. pic_height = (pic_height/8+1)*8;
  197. }
  198. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  199. val &=~(0x7f<<11);
  200. val |=(1<<17)|(yuv420<<15)|(1<<13)|(1<<12)|(1<<11);
  201. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  202. writel(0, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  203. if(pic_width%8 != 0) {
  204. nor_act_width = (pic_width/8+1)*8;
  205. } else {
  206. nor_act_width = pic_width;
  207. }
  208. if(pic_width%8 != 0) {
  209. nor_tot_width = (pic_width/8+1)*8;
  210. } else {
  211. nor_tot_width = pic_width;
  212. }
  213. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  214. val |= (0x1<<27)|(nor_act_width<<12)|(nor_tot_width);
  215. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  216. writel((pic_height<<12)|(pic_width<<0), context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  217. if(yuv420) {
  218. if(pic_height%8 != 0) {
  219. rotc_width = (pic_height/8+1)*8;
  220. } else {
  221. rotc_width = pic_height;
  222. }
  223. if(pic_width%16 != 0)
  224. rotc_src_width = (pic_width/16+1)*8;
  225. else
  226. rotc_src_width = pic_width;
  227. val = (rotc_src_width<<12)|(rotc_width<<0);
  228. writel(val, context->mmio_base + AXI_SCALE_ROTCX_FADR);
  229. val = pic_addr + (pic_height-1)*pic_width;
  230. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  231. val = pic_addr + pic_width*pic_height+(pic_height/2-1)*pic_width;
  232. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  233. } else {
  234. val = pic_addr + (pic_height-1)*pic_width;
  235. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  236. val = pic_addr + pic_width*pic_height+(pic_height-1)*pic_width;
  237. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  238. }
  239. break;
  240. }
  241. case SCALE_ROTATE_270: {
  242. if(pic_width%8 != 0)
  243. pic_width = (pic_width/8+1)*8;
  244. if(pic_height%8 != 0)
  245. pic_height = (pic_height/8+1)*8;
  246. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  247. val &=~(0x7f<<11);
  248. val |=(yuv420<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11);
  249. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  250. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  251. val &=~(0xffffff);
  252. val |=(pic_height<<12)|pic_width;
  253. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  254. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  255. val &=~(0x1f<<24);
  256. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  257. if(pic_height%8 != 0)
  258. roty_width = (pic_height/8+1)*8;
  259. else
  260. roty_width = pic_height;
  261. if(yuv420) { //for yuv420 mode.
  262. if(pic_width%16 != 0)
  263. roty_src_width = (pic_width/16+1)*16;
  264. else
  265. roty_src_width = pic_width;
  266. } else { //for yuv422 mode.
  267. if(pic_width%8 != 0)
  268. roty_src_width = (pic_width/8+1)*8;
  269. else
  270. roty_src_width = pic_width;
  271. }
  272. val = (roty_src_width<<12)|(roty_width<<0);
  273. writel(val, context->mmio_base + AXI_SCALE_ROTYX_WIDTH);
  274. if(pic_height%8 != 0)
  275. rotc_width = (pic_height/8+1)*8;
  276. else
  277. rotc_width = pic_height;
  278. if(yuv420) {
  279. if(pic_width%16 != 0)
  280. rotc_src_width = (pic_width/16+1)*8;
  281. else
  282. rotc_src_width = pic_width/2;
  283. } else {
  284. if(pic_width%8 != 0)
  285. rotc_src_width = (pic_width/8+1)*8;
  286. else
  287. rotc_src_width = pic_width;
  288. }
  289. val = (rotc_src_width<<12)|(rotc_width<<0);
  290. writel(val, context->mmio_base + AXI_SCALE_ROTCX_FADR);
  291. val = pic_addr;
  292. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  293. val = pic_addr + roty_width*roty_src_width;
  294. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  295. break;
  296. }
  297. case SCALE_ROTATE_0_MIRROR: {
  298. if(pic_width%8 != 0)
  299. pic_width = (pic_width/8+1)*8;
  300. if(pic_height%8 != 0)
  301. pic_height = (pic_height/8+1)*8;
  302. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  303. val &=~(0x7f<<11);
  304. val |=(yuv420<<15)|(1<<11);
  305. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  306. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  307. val &=~(0xffffff);
  308. val |=(pic_height<<12)|pic_width;
  309. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  310. writel(0, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  311. if(pic_width%8 != 0)
  312. nor_act_width = (pic_width/8+1)*8;
  313. else
  314. nor_act_width = pic_width;
  315. if(pic_width%8 != 0)
  316. nor_tot_width = (pic_width/8+1)*8;
  317. else
  318. nor_tot_width = pic_width;
  319. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  320. val |=0x1<<27|(nor_act_width<<12)|(nor_tot_width);
  321. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  322. val = pic_addr + (pic_height-1)*pic_width;
  323. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  324. if(yuv420)
  325. val = pic_addr + pic_width*pic_height+(pic_height/2-1)*pic_width;
  326. else
  327. val = pic_addr + pic_width*pic_height+(pic_height-1)*pic_width;
  328. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  329. break;
  330. }
  331. case SCALE_ROTATE_90_MIRROR: {
  332. if(pic_width%8 != 0)
  333. pic_width = (pic_width/8+1)*8;
  334. if(pic_height%8 != 0)
  335. pic_height = (pic_height/8+1)*8;
  336. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  337. val &=~(0x7f<<11);
  338. val |=(1<<17)|(yuv420<<15)|(1<<14)|(1<<11);
  339. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  340. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  341. val &=~(0x1f<<24);
  342. val |= (0x1<<28)|(0x1<<26)|(0x3<<24);
  343. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  344. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  345. val &=~(0xffffff);
  346. val |=(pic_height<<12)|pic_width;
  347. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  348. if(pic_height%8 != 0)
  349. roty_width = (pic_height/8+1)*8;
  350. else
  351. roty_width = pic_height;
  352. if(yuv420) {
  353. if(pic_width%16 != 0)
  354. roty_src_width = (pic_width/16+1)*16;
  355. else
  356. roty_src_width = pic_width;
  357. } else {
  358. if(pic_width%8 != 0)
  359. roty_src_width = (pic_width/8+1)*8;
  360. else
  361. roty_src_width = pic_width;
  362. }
  363. val = (roty_src_width<<12)|(roty_width<<0);
  364. writel(val, context->mmio_base + AXI_SCALE_ROTYX_WIDTH);
  365. if(pic_height%8 != 0)
  366. rotc_width = (pic_height/8+1)*8;
  367. else
  368. rotc_width = pic_height;
  369. if(yuv420) {
  370. if(pic_width%16 != 0)
  371. rotc_src_width = (pic_width/16+1)*8;
  372. else
  373. rotc_src_width = pic_width/2;
  374. } else {
  375. if(pic_width%8 != 0)
  376. rotc_src_width = (pic_width/8+1)*8;
  377. else
  378. rotc_src_width = pic_width;
  379. }
  380. val = (rotc_src_width<<12)|(rotc_width<<0);
  381. writel(val, context->mmio_base + AXI_SCALE_ROTCX_FADR);
  382. val = pic_addr + roty_width*roty_src_width-16;
  383. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  384. val = pic_addr + roty_width*roty_src_width+rotc_width*rotc_src_width-16;
  385. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  386. break;
  387. }
  388. case SCALE_ROTATE_180_MIRROR: {
  389. if(pic_width%8 != 0)
  390. pic_width = (pic_width/8+1)*8;
  391. if(pic_height%8 != 0)
  392. pic_height = (pic_height/8+1)*8;
  393. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  394. val &=~(0x7f<<11);
  395. val |=(1<<17)|(yuv420<<15)|(1<<13)|(1<<12)|(1<<11);
  396. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  397. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  398. val &=~(0xffffff);
  399. val |=(pic_height<<12)|pic_width;
  400. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  401. writel(0, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  402. if(pic_width%8 != 0)
  403. nor_act_width = (pic_width/8+1)*8;
  404. else
  405. nor_act_width = pic_width;
  406. if(pic_width%8 != 0)
  407. nor_tot_width = (pic_width/8+1)*8;
  408. else
  409. nor_tot_width = pic_width;
  410. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  411. val |=(nor_act_width<<12)|(nor_tot_width);
  412. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  413. val = pic_addr;
  414. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  415. val = pic_addr + pic_width*pic_height;
  416. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  417. break;
  418. }
  419. case SCALE_ROTATE_270_MIRROR: {
  420. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  421. val &=~(0x7f<<11);
  422. val |=(yuv420<<15)|(1<<14)|(1<<11);
  423. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  424. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  425. val &=~(0x1f<<24);
  426. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL_REG);
  427. val = readl(context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  428. val &=~(0xffffff);
  429. val |=(pic_height<<12)|pic_width;
  430. writel(val, context->mmio_base + AXI_SCALE_ROTATA_IMG_SIZE);
  431. if(pic_height%8 != 0)
  432. roty_width = (pic_height/8+1)*8;
  433. else
  434. roty_width = pic_height;
  435. if(yuv420) {
  436. if(pic_width%16 != 0)
  437. roty_src_width = (pic_width/16+1)*8;
  438. else
  439. roty_src_width = pic_width;
  440. } else {
  441. if(pic_width%8 != 0)
  442. roty_src_width = (pic_width/8+1)*8;
  443. else
  444. roty_src_width = pic_width;
  445. }
  446. val = (roty_src_width<<12)|(roty_width<<0);
  447. writel(val, context->mmio_base + AXI_SCALE_ROTYX_WIDTH);
  448. if(pic_height%8 != 0)
  449. rotc_width = (pic_height/8+1)*8;
  450. else
  451. rotc_width = pic_height;
  452. if(yuv420) {
  453. if(pic_width%16 != 0)
  454. rotc_src_width = (pic_width/16+1)*8;
  455. else
  456. rotc_src_width = pic_width/2;
  457. } else {
  458. if(pic_width%8 != 0)
  459. rotc_src_width = (pic_width/8+1)*8;
  460. else
  461. rotc_src_width = pic_width;
  462. }
  463. val = (rotc_src_width<<12)|(rotc_width<<0);
  464. writel(val, context->mmio_base + AXI_SCALE_ROTCX_FADR);
  465. val = pic_addr;
  466. writel(val, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  467. val = pic_addr + roty_width*roty_src_width;
  468. writel(val, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  469. break;
  470. }
  471. default:
  472. break;
  473. }
  474. }
  475. static void scale_peaking_denoise(struct ark_scale_context *context, unsigned int dst_width ,unsigned int dst_height)
  476. {
  477. //denoise
  478. #define hand_sel 1 //Hand_sel
  479. #define denoise_Bypass 0//0x2//0//0 //Bypass
  480. #define blank_hand 0xff//0x7ff//16
  481. #define valid_blank_hand 0xff//0x7ff//16
  482. #define K_Y 0x80//0xfff//0xfff//80
  483. #define K_CC 0x80//0xff//0xff//80
  484. //peking
  485. #define Peaking_bypass 0//0x2//0x2//0
  486. #define peaking_hand_sel 1
  487. #define hv_peaking_sel 0
  488. #define lgainh 10
  489. #define mgainh 10
  490. #define hgainh 5
  491. #define lgainv 30//0x1e
  492. #define mgainv 20
  493. #define hgainv 15
  494. #define gaind45 20
  495. #define gaind135 20
  496. #define core_max 50//0x32
  497. #define core_min 10//0xa
  498. unsigned int Pixel_hand = dst_width;
  499. unsigned int hsync_hand = dst_height;
  500. unsigned int valid_pixel_hand = dst_width;
  501. unsigned int val = 0;
  502. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  503. val &= ~(1<<19);
  504. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  505. val = (Peaking_bypass<<28) | (hv_peaking_sel<<27) | (peaking_hand_sel<<26) |
  506. (hand_sel<<25) | (denoise_Bypass<<23) | (blank_hand<<12) | (Pixel_hand<<0);
  507. writel(val, context->mmio_base + AXI_SCALE_PD_CTL1);
  508. val = (valid_pixel_hand<<12) | (hsync_hand<<0);
  509. writel(val, context->mmio_base + AXI_SCALE_PD_CTL2);
  510. val = (K_CC<<24) | (K_Y<<12) | (valid_blank_hand<<0);
  511. writel(val, context->mmio_base + AXI_SCALE_DENOISE_CTL3);
  512. val = (lgainv<<24) | (hgainh<<16) | (mgainh<<8) | (lgainh<<0);
  513. writel(val, context->mmio_base + AXI_SCALE_PEAKING_CTL4);
  514. val = (gaind135<<24) | (gaind45<<16) | (hgainv<<8) | (mgainv<<0);
  515. writel(val, context->mmio_base + AXI_SCALE_PEAKING_CTL5);
  516. val = (core_min<<8) | (core_max<<0);
  517. writel(val, context->mmio_base + AXI_SCALE_PEAKING_CTL6);
  518. }
  519. void scale_softreset(struct ark_scale_context *context)
  520. {
  521. u32 val;
  522. if(context) {
  523. if(context->softreset_reg >= 0) {
  524. int reg = context->softreset_reg;
  525. int offset = context->softreset_offset;
  526. val = readl(context->sys_base + reg);
  527. val &= ~(1 << offset);
  528. writel(val, context->sys_base + reg);
  529. udelay(10);
  530. val |= (1 << offset);
  531. writel(val, context->sys_base + reg);
  532. } else {
  533. //Only arkn141 platform.
  534. val = readl(context->sys_base + SYS_SOFT_RSTNB);
  535. val &= ~(1 << 10);
  536. writel(val, context->sys_base + SYS_SOFT_RSTNB);
  537. udelay(10);
  538. val |= (1 << 10);
  539. writel(val, context->sys_base + SYS_SOFT_RSTNB);
  540. }
  541. }
  542. }
  543. static int ark_scale_set_param(struct ark_scale_context *context, struct ark_scale_param *param)
  544. {
  545. int ret = SCALE_RET_OK;
  546. int do_horz_down_scalar = 0; // down scalar
  547. int yuv_order = (param->iformat >> 8) & 0xFF;
  548. int format = param->iformat & 0xFF;
  549. unsigned int vcut = param->up_cut + param->bottom_cut;
  550. unsigned int hcut = param->left_cut + param->right_cut;
  551. u32 val;
  552. if(context->soc_type == SOC_TYPE_ARK1668E) {
  553. writel(0x0, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  554. writel((1<<28)|(1<<23), context->mmio_base + AXI_SCALE_PD_CTL1); //disable demoise peaking
  555. }
  556. do {
  557. //write back middle finish, write back bresp error, write back frame finish)
  558. writel(0x7, context->mmio_base + AXI_SCALE_CLCD_INT_CLR);
  559. //write back bresp error, write back frame finish)
  560. if(context->soc_type == SOC_TYPE_ARK1668E) {
  561. writel((1 << 0), context->mmio_base + AXI_SCALE_INT_CTL);
  562. } else {
  563. writel((1 << 0) | (1 << 1), context->mmio_base + AXI_SCALE_INT_CTL);
  564. }
  565. writel(0, context->mmio_base + AXI_SCALE_RESERVED);
  566. writel(0x0<<29|0x0<<25|0x0<<24|0x8<<20|0x2<<16|0x0<<12|0x0<<8|0x0<<6|0x0<<4|0x0<<3|0x0<<2|format<<0,
  567. context->mmio_base + AXI_SCALE_CONTROL);
  568. val = readl(context->mmio_base + AXI_SCALE_CONTROL);
  569. if (format == SCALE_FORMAT_YUYV)
  570. val |= yuv_order << 6;
  571. else if (format == SCALE_FORMAT_YUV422 || format == SCALE_FORMAT_YUV420)
  572. val |= (yuv_order & 1) << 2;
  573. writel(val, context->mmio_base + AXI_SCALE_CONTROL);
  574. if (param->iwidth == param->owidth && param->iheight == param->oheight &&
  575. param->iwidth == param->iwinwidth && param->iheight == param->iwinheight) {
  576. val |= (1<<5);
  577. writel(val, context->mmio_base + AXI_SCALE_CONTROL);
  578. }
  579. if(context->soc_type == SOC_TYPE_ARK1668E) {
  580. //height +100 means add scale margin(\D3\E0\C1\BF).
  581. writel(((param->iheight+100+vcut) << 12) | (param->iwidth << 0), context->mmio_base + AXI_SCALE_VIDEO_SOURCE_SIZE);
  582. writel((param->iwinheight+100+vcut) << 12 | param->iwinwidth << 0, context->mmio_base + AXI_SCALE_VIDEO_WINDOW_SIZE);
  583. } else /* if(context->soc_type == SOC_TYPE_ARKN141) */ {
  584. writel((param->iheight << 12) | (param->iwidth << 0), context->mmio_base + AXI_SCALE_VIDEO_SOURCE_SIZE);
  585. writel(param->iwinheight << 12 | param->iwinwidth << 0, context->mmio_base + AXI_SCALE_VIDEO_WINDOW_SIZE);
  586. }
  587. /* y_positong<<12 | x_position */
  588. writel((param->iy << 12) | (param->ix << 0), context->mmio_base + AXI_SCALE_VIDEO_WINDOW_POINT);
  589. /* Y (YUV/YUYV) data start address.*/
  590. writel(param->iyaddr, context->mmio_base + AXI_SCALE_VIDEO_ADDR1);
  591. /* U or UV data start address. */
  592. if(!param->iuaddr) {
  593. if(format == SCALE_FORMAT_Y_UV420 || \
  594. format == SCALE_FORMAT_YUV420 || \
  595. format == SCALE_FORMAT_Y_UV422 || \
  596. format == SCALE_FORMAT_YUV422) {
  597. param->iuaddr = param->iyaddr + ((param->iwidth+0xF)&(~0xF)) * ((param->iheight+0xF)&(~0xF));
  598. } else {
  599. param->iuaddr = 0;
  600. }
  601. }
  602. writel(param->iuaddr, context->mmio_base + AXI_SCALE_VIDEO_ADDR2);
  603. /* V data start address. */
  604. if(!param->ivaddr) {
  605. if(format == SCALE_FORMAT_Y_UV420) {
  606. param->ivaddr = 0;
  607. } else if(format == SCALE_FORMAT_YUV420) {
  608. param->ivaddr = param->iuaddr + ((param->iwidth+0xF)&(~0xF)) * ((param->iheight+0xF)&(~0xF)) / 4;
  609. } else if(format == SCALE_FORMAT_Y_UV422) {
  610. param->ivaddr = param->iuaddr;
  611. } else if(format == SCALE_FORMAT_YUV422) {
  612. param->ivaddr = param->iuaddr + ((param->iwidth+0xF)&(~0xF)) * ((param->iheight+0xF)&(~0xF)) / 2;
  613. } else {
  614. param->ivaddr = 0;
  615. }
  616. }
  617. writel(param->ivaddr, context->mmio_base + AXI_SCALE_VIDEO_ADDR3);
  618. /*scale output size */
  619. writel((param->oheight << 12) | (param->owidth << 0), context->mmio_base + AXI_SCALE_VIDEO_SIZE);
  620. if (param->iwinwidth > (param->owidth + hcut) * 3 / 2)
  621. do_horz_down_scalar = 1;
  622. if( do_horz_down_scalar == 0 )
  623. writel(0<<9| 0<<8 | 1<<7| 0<<6 | 1<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1 | 0,
  624. context->mmio_base + AXI_SCALE_SCALE_CTL);
  625. else
  626. writel(0<<9| 1<<8 | 1<<7| 1<<6 | 1<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1 | 0,
  627. context->mmio_base + AXI_SCALE_SCALE_CTL);
  628. writel(512<<11 | 0<<0, context->mmio_base + AXI_SCALE_SCALE_VXMOD); /*V_xmod_odd_init<<11 | V_xmod_even_init */
  629. /*left cut number in line scaler<<18 | hfz */
  630. val = param->left_cut << 18 | (param->iwinwidth * 1024 / (param->owidth + hcut));
  631. writel(val, context->mmio_base + AXI_SCALE_SCALE_CTL0);
  632. /* Up cut line number in veritical scaler <<18 | vfz */
  633. val = param->up_cut << 18 | (param->iwinheight * 1024 / (param->oheight + vcut + 4));
  634. writel(val, context->mmio_base + AXI_SCALE_SCALE_CTL1);
  635. /* right_cut_num<<8 | bottom_cut_num */
  636. val = param->right_cut << 8 | param->bottom_cut;
  637. writel(val, context->mmio_base + AXI_SCALE_RIGHT_BOTTOM_CUT_NUM);
  638. /* check output uaddr */
  639. if(!param->ouaddr) {
  640. if((param->oformat == SCALE_OUT_FORMAT_Y_UV420) || (param->oformat == SCALE_OUT_FORMAT_Y_UV422)) {
  641. param->ouaddr = param->oyaddr + ((param->owidth+0xF)&(~0xF)) * ((param->oheight+0xF)&(~0xF));
  642. } else if(param->oformat == SCALE_OUT_FORMAT_YUYV) {
  643. param->ouaddr = 0;
  644. }
  645. }
  646. //param->ovaddr = 0;
  647. if(context->soc_type == SOC_TYPE_ARKN141) {
  648. /*The number of the horizontal pix in write back ram*/
  649. writel(param->owidth, context->mmio_base + AXI_SCALE_WB_DATA_HSIZE_RAM);
  650. writel(param->oyaddr, context->mmio_base + AXI_SCALE_WB_DEST_YADDR);
  651. writel(param->ouaddr, context->mmio_base + AXI_SCALE_WB_DEST_UADDR);
  652. writel(param->ovaddr, context->mmio_base + AXI_SCALE_WB_DEST_VADDR);
  653. } else if(context->soc_type == SOC_TYPE_ARK1668E) {
  654. int index;
  655. //eliminate the filter line H.
  656. val = readl(context->mmio_base + AXI_SCALE_SCALE_CTL);
  657. val &= ~((1<<8)|(1<<6)|(1<<11)|(1<<12));
  658. val |= (1<<12);
  659. writel(val, context->mmio_base + AXI_SCALE_SCALE_CTL);
  660. //set ratate initilize value. it will be set again soon.
  661. writel(0x00988000, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  662. //set filetr initilize value, it will be set again soon.
  663. writel(0x64, context->mmio_base + AXI_SCALE_VFILTER_CLR);
  664. //set default value.
  665. writel(0xFF, context->mmio_base + AXI_SCALE_WB_DATA_HSIZE_RAM);
  666. #if 1 //filter.
  667. writel(0x0, context->mmio_base + AXI_SCALE_VFILTER_CLR);
  668. writel(0x0, context->mmio_base + AXI_SCALE_VFILTER_COEFF);
  669. index = get_scaler_cof(param->iwinheight, param->oheight);
  670. if(index < 16) {
  671. val = (ver_cof[index][1]<<24) | (ver_cof[index][0]<<16) | (1<<14) | param->iwinwidth;
  672. writel(val, context->mmio_base + AXI_SCALE_VFILTER_CLR);
  673. val = (ver_cof[index][5]<<24) | (ver_cof[index][4]<<16) | (ver_cof[index][3]<<8) | ver_cof[index][2];
  674. writel(val, context->mmio_base + AXI_SCALE_VFILTER_COEFF);
  675. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  676. val &=~(0xFF<<20);
  677. val |=(ver_cof[index][6]<<20);;
  678. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  679. val = readl(context->mmio_base + AXI_SCALE_SCALE_CTL);
  680. val &=~(0x1<<24);
  681. val |=(1<<24);
  682. writel(val, context->mmio_base + AXI_SCALE_SCALE_CTL);
  683. }
  684. #endif
  685. writel(param->oyaddr, context->mmio_base + AXI_SCALE_ROTATA_Y_FADR);
  686. writel(param->ouaddr, context->mmio_base + AXI_SCALE_ROTATA_C_FADR);
  687. if(param->oformat == SCALE_OUT_FORMAT_Y_UV420) {
  688. scale_rotate(context, SCALE_FORMAT_YUV420, param->rotate, param->owidth, param->oheight, param->oyaddr);
  689. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  690. val &= ~((1<<15) | (1<<28));
  691. val |=(1<<15);
  692. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  693. } else if(param->oformat == SCALE_OUT_FORMAT_Y_UV422) {
  694. scale_rotate(context, SCALE_FORMAT_YUV422, param->rotate, param->owidth, param->oheight, param->oyaddr);
  695. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  696. val &= ~((1<<15) | (1<<28));
  697. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  698. } else if(param->oformat == SCALE_OUT_FORMAT_YUYV) {
  699. scale_rotate(context, SCALE_FORMAT_YUV422, param->rotate, param->owidth, param->oheight, param->oyaddr);
  700. val = readl(context->mmio_base + AXI_SCALE_ROTATA_CTL);
  701. val |=(1<<17) | (1<<28);
  702. writel(val, context->mmio_base + AXI_SCALE_ROTATA_CTL);
  703. }
  704. }
  705. writel(0x3, context->mmio_base + AXI_SCALE_EN);
  706. } while (0);
  707. scale_peaking_denoise(context, param->owidth, param->oheight);
  708. return ret;
  709. }
  710. static inline void ark_scale_start_writeback(struct ark_scale_context *context)
  711. {
  712. writel(1, context->mmio_base + AXI_SCALE_WB_START);
  713. udelay(50);
  714. writel(0, context->mmio_base + AXI_SCALE_WB_START);
  715. }
  716. static int ark_scale_wait_finish_int(struct ark_scale_context *context)
  717. {
  718. int ret = wait_event_interruptible_timeout(context->waitq,
  719. context->busy == 0, msecs_to_jiffies(100));
  720. if (ret < 0)
  721. return ret;
  722. if (ret == 0) {
  723. printk(KERN_ALERT "wait scale finish timeout.\n");
  724. return -ETIMEDOUT;
  725. }
  726. return 0;
  727. }
  728. int ark_scale_get_busy_status(struct ark_scale_context *context)
  729. {
  730. return context->busy;
  731. }
  732. EXPORT_SYMBOL(ark_scale_get_busy_status);
  733. int ark_scale_start_nowait(struct ark_scale_context *context, struct ark_scale_param *param)
  734. {
  735. if (unlikely(down_interruptible(&context->scale_sem))) {
  736. printk(KERN_ALERT "down_interruptible scale error\n");
  737. return -1;
  738. }
  739. if (unlikely(context->busy)) {
  740. printk(KERN_ALERT "%s error! scale is busy now.\n", __FUNCTION__);
  741. return -1;
  742. }
  743. context->busy = 1;
  744. /* clk_disable_unprepare(context->clk);
  745. scale_softreset(context);
  746. clk_prepare_enable(context->clk); */
  747. ark_scale_set_param(context, param);
  748. ark_scale_start_writeback(context);
  749. return 0;
  750. }
  751. EXPORT_SYMBOL(ark_scale_start_nowait);
  752. int ark_scale_wait_idle(struct ark_scale_context *context)
  753. {
  754. int ret;
  755. ret = ark_scale_wait_finish_int(context);
  756. up(&context->scale_sem);
  757. return ret;
  758. }
  759. EXPORT_SYMBOL(ark_scale_wait_idle);
  760. int ark_scale_start(struct ark_scale_context *context, struct ark_scale_param *param)
  761. {
  762. int ret;
  763. ret = ark_scale_start_nowait(context, param);
  764. if (ret < 0) {
  765. up(&context->scale_sem);
  766. return ret;
  767. }
  768. ret = ark_scale_wait_finish_int(context);
  769. up(&context->scale_sem);
  770. return ret;
  771. }
  772. EXPORT_SYMBOL(ark_scale_start);
  773. int ark_scale_dev_init(struct ark_scale_context *context)
  774. {
  775. clk_disable_unprepare(context->clk);
  776. scale_softreset(context);
  777. clk_prepare_enable(context->clk);
  778. spin_lock_init(&context->lock);
  779. init_waitqueue_head(&context->waitq);
  780. return 0;
  781. }
  782. irqreturn_t ark_scale_intr_handler(int irq, void *dev_id)
  783. {
  784. struct ark_scale_device *scale = (struct ark_scale_device *)dev_id;
  785. struct ark_scale_context *context = &scale->context;
  786. unsigned int status = readl(context->mmio_base + AXI_SCALE_INT_STATUS);
  787. do {
  788. if(status & (1 << 2)) // write back bresp error
  789. break;
  790. // AXI SCALE write back middle finish interupt
  791. //if(status & (1 << 5))
  792. //break;
  793. if(status & (1 << 0)) // write back frame finish interupt
  794. break;
  795. return IRQ_NONE; //add.
  796. } while(0);
  797. writel(0, context->mmio_base + AXI_SCALE_EN);
  798. writel(0x07, context->mmio_base + AXI_SCALE_CLCD_INT_CLR);
  799. context->busy = 0;
  800. wake_up_interruptible(&context->waitq);
  801. return IRQ_HANDLED;
  802. }