Qualcomm DSI porting guide

Hi, Linux newbie here. Trying to get a mipi display working. Have built and installed kernel. Have built the LK bootloader. Using the DSI porting guide I get to section 2.1 and don’t understand what to do in step 1.

Do I copy and paste the code from codeaurora in to a new file? Can’t see how to download the patch.
Second when I try and run the command ‘patch -p1 …’ It asks what I want to patch against. I have no clue.

If anyone can give me some pointers I would very much appreciate it.

Steve

I assume you want to run the QCOM Android here, not Linaro debian/oe ?
How/form which repository did yo downloaded kernel source ?

You can use git to clone the full repository.
You can also click on plain format and save the patch from your web browser.
Then you need to copy the patch in the root kernel source tree and you should be able to apply it with patch -p1.

Sorry, I forgot to specify. I am running Debian Buster.

The document you are referring to is quite the puzzle for Linux newbies, recently went to the same experience :slight_smile: . Anyway I think this is geared towards Android/Linux on Codeaurora Framework. That said, I skipped all the LK stuff as well as section 2.1, afaik that’s only useful if you want to use a panel driver that is listed there and not present in the kernel source.

For Debian/Linux have a look here: https://github.com/freedreno/freedreno/wiki/DSI-Panel-Driver-Porting

As a newbie myself, I was completely intimidated by the whole upstream/downstream thing. But in short: For Debian (and AOSP) you’ll want to follow the upstream method. Codeaurora-Android is downstream.

Yes if you’re using debian, you do not need to follow the guide for kernel/lk changes. Check firstly If you’re device is already supported by the kernel or let me know which device it is. You’ll need to add your device in the Device tree.

This has been already discussed in previous some previous topics:

As a newbie myself, I was completely intimidated by the whole
upstream/downstream thing. But in short: if I’m correct you want to
follow the upstream method. Codeaurora is downstream.

Thank for sharing your thoughts on this. Some of us are so immersed
in this sort of terminology we need communication problems like that
spelling out to us!

You can also think of it as Android and GNU/Linux (or regular Linux if
you prefer). The kernels provided by the Android and GNU/Linux builds
are radically different… driver level documentation for one generally
does not apply to the other.

The kernel used for GNU/Linux build is fairly closely aligned to the
mainline kernel (a.k.a. the “upstream”, maintained by Linus Torvalds)
and thus most documentation that applies to the mainline kernel also
applies to the GNU/Linux builds.

But AOSP also uses drm for MIPI DSI panel support, that’s similar to GNU/Linux or not?

And Codeaurora with the dtsi based panel configuration, does that have a generic drm based driver under the hood as well?

But AOSP also uses drm for MIPI DSI panel support, that’s similar to GNU/Linux or not?

Are you talking about the Linaro snapshots (rather than Qualcomm
releases)?
http://snapshots.linaro.org/96boards/dragonboard410c/linaro/aosp

Snapshots are unreleased code and we deliberately put them on a
different file server. AFAIK no documentation describes them[1].
However, yes, these snapshots are built on the same kernel as the Debian
builds so for the most part drivers work pretty much like the
Debian/OpenEmbedded builds.

To be clear you are 100% welcome to play with and hack on our unreleased
code. We even secretly like it! However it does come with a
non-guarantee sometimes phrased as: if it breaks then you get to keep
both halves
(and, to be honest, we’ll even still do our best on the
forum to help you glue your halves back together).

And Codeaurora with the dtsi based panel configuration, does that have
a generic drm based driver under the hood as well?

CodeAurora is not one thing. It contains a greater variety of kernels
than I could count (and most of which I don’t know much about) see:
https://www.codeaurora.org/projects/all-active-projects

As a result the CodeAurora repos host both the source for Qualcomm
Android and a derivation of Linaro RPB (OpenEmbedded for MSM).

[1] This is not strictly true. There is a document that describe how to
build this code… but it is tagged with “This work is experimental”
to scare people away :wink:

No I was talking about Google AOSP master (with HiKey). Anyway this going way off-topic.

Thanks everyone for the ideas. will get working on them.

The Display is a TST055HDHI-01C. 720x 1280.
The driver chip is an ili9881c

Thanks
Steve

I recently did my first DSI panel porting with an ili9881c based panel. I can’t share any code but I could spot issues if you run into them. Good luck!

This is the information I received from the manufacturer.
I just don’t know the next step. Where / how do I install this?

Sorry, just a newbie but really need to get this working.
Thanks,
Steve
(dragonboard 410c, linux)

// F055A15-601

#define LCM_ID_ILI9881C
static unsigned int lcm_compare_id(void)
{
#if 1
int array[4];
char buffer[5];
char id_high=0;
char id_midd=0;
char id_low=0;
int id=0;

    //Do reset here
    SET_RESET_PIN(1);
    SET_RESET_PIN(0);
    MDELAY(25);       
    SET_RESET_PIN(1);
    MDELAY(120);      

    array[0]=0x00063902;
    array[1]=0x018198ff;

    dsi_set_cmdq(array, 2, 1);
    MDELAY(10);

    array[0]=0x00033700;
    dsi_set_cmdq(array, 1, 1);
    //read_reg_v2(0x04, buffer, 3);//if read 0x04,should get 0x008000,that is both OK.

    read_reg_v2(0x00, buffer,1);
    id_high = buffer[0]; ///////////////////////0x98

    read_reg_v2(0x01, buffer,1);
    id_midd = buffer[0]; ///////////////////////0x81

    read_reg_v2(0x02, buffer,1);
    id_low = buffer[0]; ////////////////////////0x0C

    id =(id_high << 16) | (id_midd << 8) | id_low;

#if defined(BUILD_LK)
printf(“zrl_lk – ili9806e 0x%x , 0x%x , 0x%x, 0x%x \n”, id_high, id_midd, id_low, id);
#else
printk(“zrl_kernel – ili9806e 0x%x , 0x%x , 0x%x, 0x%x \n”, id_high, id_midd, id_low, id);
#endif

   return (id == LCM_ID_ILI9881)?1:0;

#else
return 1;//0;
#endif

}

Void INI(void)
{
reset=1;
Delay(30);
reset=0;
Delay(100);
reset=1;
Delay(100);

//************* Start Initial Sequence **********//

{0xFF, 3, {0x98,0x81,0x03}},//PAGE 3
{0x01, 1, {0x00}},
{0x02, 1, {0x00}},
{0x03, 1, {0x53}},
{0x04, 1, {0x53}},
{0x05, 1, {0x13}},
{0x06, 1, {0x04}},
{0x07, 1, {0x02}},
{0x08, 1, {0x02}},
{0x09, 1, {0x00}},
{0x0a, 1, {0x00}},
{0x0b, 1, {0x00}},
{0x0c, 1, {0x00}},
{0x0d, 1, {0x00}},
{0x0e, 1, {0x00}},
{0x0f, 1, {0x00}},

{0x10, 1, {0x00}},
{0x11, 1, {0x00}},
{0x12, 1, {0x00}},
{0x13, 1, {0x00}},
{0x14, 1, {0x00}},
{0x15, 1, {0x00}},
{0x16, 1, {0x00}},
{0x17, 1, {0x00}},
{0x18, 1, {0x00}},
{0x19, 1, {0x00}},
{0x1a, 1, {0x00}},
{0x1b, 1, {0x00}},
{0x1c, 1, {0x00}},
{0x1d, 1, {0x00}},
{0x1e, 1, {0xC0}},
{0x1f, 1, {0x80}},

{0x20, 1, {0x02}},
{0x21, 1, {0x09}},
{0x22, 1, {0x00}},
{0x23, 1, {0x00}},
{0x24, 1, {0x00}},
{0x25, 1, {0x00}},
{0x26, 1, {0x00}},
{0x27, 1, {0x00}},
{0x28, 1, {0x55}},
{0x29, 1, {0x03}},
{0x2a, 1, {0x00}},
{0x2b, 1, {0x00}},
{0x2c, 1, {0x00}},
{0x2d, 1, {0x00}},
{0x2e, 1, {0x00}},
{0x2f, 1, {0x00}},

{0x30, 1, {0x00}},
{0x31, 1, {0x00}},
{0x32, 1, {0x00}},
{0x33, 1, {0x00}},
{0x34, 1, {0x03}},
{0x35, 1, {0x00}},
{0x36, 1, {0x05}},
{0x37, 1, {0x00}},
{0x38, 1, {0x3C}},
{0x39, 1, {0x00}},
{0x3a, 1, {0x40}},
{0x3b, 1, {0x40}},
{0x3c, 1, {0x00}},
{0x3d, 1, {0x00}},
{0x3e, 1, {0x00}},
{0x3f, 1, {0x00}},

{0x40, 1, {0x00}},
{0x41, 1, {0x00}},
{0x42, 1, {0x00}},
{0x43, 1, {0x00}},
{0x44, 1, {0x00}},

{0x50, 1, {0x01}},
{0x51, 1, {0x23}},
{0x52, 1, {0x45}},
{0x53, 1, {0x67}},
{0x54, 1, {0x89}},
{0x55, 1, {0xab}},
{0x56, 1, {0x01}},
{0x57, 1, {0x23}},
{0x58, 1, {0x45}},
{0x59, 1, {0x67}},
{0x5a, 1, {0x89}},
{0x5b, 1, {0xab}},
{0x5c, 1, {0xcd}},
{0x5d, 1, {0xef}},

{0x5e, 1, {0x01}},
{0x5f, 1, {0x14}},
{0x60, 1, {0x15}},
{0x61, 1, {0x0C}},
{0x62, 1, {0x0D}},
{0x63, 1, {0x0E}},
{0x64, 1, {0x0F}},
{0x65, 1, {0x10}},
{0x66, 1, {0x11}},
{0x67, 1, {0x08}},
{0x68, 1, {0x02}},
{0x69, 1, {0x0A}},
{0x6a, 1, {0x02}},
{0x6b, 1, {0x02}},
{0x6c, 1, {0x02}},
{0x6d, 1, {0x02}},
{0x6e, 1, {0x02}},
{0x6f, 1, {0x02}},

{0x70, 1, {0x02}},
{0x71, 1, {0x02}},
{0x72, 1, {0x06}},
{0x73, 1, {0x02}},
{0x74, 1, {0x02}},
{0x75, 1, {0x14}},
{0x76, 1, {0x15}},
{0x77, 1, {0x0F}},
{0x78, 1, {0x0E}},
{0x79, 1, {0x0D}},
{0x7a, 1, {0x0C}},
{0x7b, 1, {0x11}},
{0x7c, 1, {0x10}},
{0x7d, 1, {0x06}},
{0x7e, 1, {0x02}},
{0x7f, 1, {0x0A}},

{0x80, 1, {0x02}},
{0x81, 1, {0x02}},
{0x82, 1, {0x02}},
{0x83, 1, {0x02}},
{0x84, 1, {0x02}},
{0x85, 1, {0x02}},
{0x86, 1, {0x02}},
{0x87, 1, {0x02}},
{0x88, 1, {0x08}},
{0x89, 1, {0x02}},
{0x8A, 1, {0x02}},

{0xFF, 3, {0x98,0x81,0x04}},
{0x00, 1, {0x80}}, //MIPI 4 lane
{0x6C, 1, {0x15}},
{0x6E, 1, {0x2F}}, //2B
{0x6F, 1, {0x55}}, //35
{0x3A, 1, {0xA4}},
{0x8D, 1, {0x1F}}, //VGL clamp -11V=1A -12V=1F
{0x87, 1, {0xBA}}, //ESD
{0x26, 1, {0x76}},
{0xB2, 1, {0xD1}},
{0x88, 1, {0x0B}},

{0xFF, 3, {0x98,0x81,0x01}},
//{0x22, 1, {0x0A}}, // Õýɨ
{0x22, 1, {0x09}}, // ·´É¨
{0x31, 1, {0x00}},
{0x53, 1, {0x8A}}, //VCOM1
{0x55, 1, {0x88}}, //VCOM2
{0x50, 1, {0xC0}}, //¶Ô±È¶È µ÷´ó±ä°×µ÷С±äºÚ
{0x51, 1, {0xC0}}, //¶Ô±È¶È µ÷´ó±ä°×µ÷С±äºÚ
{0x60, 1, {0x2B}}, //SDT 14

{0xA0, 1, {0x08}}, //VP255 Gamma P
{0xA1, 1, {0x1E}}, //VP251
{0xA2, 1, {0x2C}}, //VP247
{0xA3, 1, {0x15}}, //VP243
{0xA4, 1, {0x18}}, //VP239
{0xA5, 1, {0x2A}}, //VP231
{0xA6, 1, {0x1F}}, //VP219
{0xA7, 1, {0x1F}}, //VP203
{0xA8, 1, {0x85}}, //VP175
{0xA9, 1, {0x1C}}, //VP144
{0xAA, 1, {0x2A}}, //VP111
{0xAB, 1, {0x72}}, //VP80
{0xAC, 1, {0x1A}}, //VP52
{0xAD, 1, {0x18}}, //VP36
{0xAE, 1, {0x4C}}, //VP24
{0xAF, 1, {0x20}}, //VP16
{0xB0, 1, {0x26}}, //VP12
{0xB1, 1, {0x4A}}, //VP8
{0xB2, 1, {0x57}}, //VP4
{0xB3, 1, {0x2C}}, //VP0

{0xC0, 1, {0x08}}, //VN255 GAMMA N
{0xC1, 1, {0x1B}}, //VN251
{0xC2, 1, {0x27}}, //VN247
{0xC3, 1, {0x12}}, //VN243
{0xC4, 1, {0x14}}, //VN239
{0xC5, 1, {0x25}}, //VN231
{0xC6, 1, {0x1A}}, //VN219
{0xC7, 1, {0x1D}}, //VN203
{0xC8, 1, {0x7A}}, //VN175
{0xC9, 1, {0x1A}}, //VN144
{0xCA, 1, {0x28}}, //VN111
{0xCB, 1, {0x6B}}, //VN80
{0xCC, 1, {0x1F}}, //VN52
{0xCD, 1, {0x1D}}, //VN36
{0xCE, 1, {0x52}}, //VN24
{0xCF, 1, {0x24}}, //VN16
{0xD0, 1, {0x2D}}, //VN12
{0xD1, 1, {0x47}}, //VN8
{0xD2, 1, {0x55}}, //VN4
{0xD3, 1, {0x2C}}, //VN0

{0xFF, 3, {0x98,0x81,0x00}},//PAGE 0

{0x11, 0, {0x00}},
{REGFLAG_DELAY, 120, {}},
{0x29, 0, {0x00}},
{REGFLAG_DELAY, 50, {}},

}

static struct LCM_setting_table lcm_sleep_out_setting[] = {
// Sleep Out
{0x11, 1, {0x00}},
{REGFLAG_DELAY, 120, {}},
// Display ON
{0x29, 1, {0x00}},
{REGFLAG_DELAY, 100, {}},

{REGFLAG_END_OF_TABLE, 0x00, {}}
};

static struct LCM_setting_table lcm_deep_sleep_mode_in_setting[] = {
// Display off sequence
{0x28, 1, {0x00}},
{REGFLAG_DELAY, 10, {}},
// Sleep Mode OnPreformatted text
{0x10, 1, {0x00}},
{REGFLAG_DELAY, 120, {}},

{REGFLAG_END_OF_TABLE, 0x00, {}}
};

Oh this isn’t so cryptic as the TXT file with bare bytecode that I got with my panels.

You basically have to take a random panel from $KERNEL_DIR/drivers/gpu/drm/panel, copy and rename it, define it as a module in Kconfig and enable it in defconfig, reference it in Makefile and replace the relevant pieces from the above code in the right places. To get the right panel timings, the Excel sheet used in the Qualcomm porting guide for Android could be useful.

@Genoil can you please elaborate on how to enable the driver in defconfig? It looks like I have the rest of the process complete.