Short update:
Am 27.04.2016 um 19:38 schrieb H. Nikolaus Schaller hns@goldelico.com:
Hi,
Am 26.04.2016 um 18:31 schrieb Tomi Valkeinen tomi.valkeinen@ti.com:
Hi,
So just a quick reply, I didn't go through all the material:
no problem, it was already extremely valuable.
On 26/04/16 16:12, H. Nikolaus Schaller wrote:
Hi Tomi, I am working to cast the timing calculations and register setup for our ssd2858 video processor and rotator into a native omapdss driver.
The setup is that the OMAP5 MIPI channel A drives the inputs of the ssd encoder and the MIPITX output of the encoder drives the panel, for which we have a separate driver that works (if we bridge the ssd2858 chip and the panel directly receives the MIPI video stream).
I am still fighting with correct architecture for this and getting the pieces to interwork.
I have tried to follow the design patterns and code of the encoer-tfp410 and encoder-opa362 and the panel is initialized and calls the ssd2858_connect() function. I.e. I assume the DT nodes are correctly setting up the basics.
The 'port' in 'dss' node is for MIPI DPI outputs. You should not have anything there.
Indeed, this seems to be a relict of earlier experiments. There is no reference &dsi_out anywhere.
The ports and endpoints are used to connect the video path. You have DSS DSI, ssd2858 encoder and panel, and thus you should have the endpoints go between those.
Yes.
The parent-child relationships of the nodes represent the command path. If I understand right, the ssd2858 is a DSI peripheral, so it should be under DSS's DSI node. Similarly, if the panel is a DSI panel, it should be under ssd2858 node.
Well, this was already big discussion because DT maintainers now prefer parent/child relationship which IMHO removes a lot of flexibility. Would be like all subroutines used in a function must be defined between { and }...
But I think that can easily be changed later.
However, this setup requires ssd2858 to manage its children, and that's never been done. So ssd2858 should create a DSI bus to which the panel registers (similarly to what DSS's DSI does). I'm not sure if there are problems there.
Basically I have this "bus" but not properly represented by DT subnodes. If I remember correctly the TFP410 doesn't have it either.
And it is indeed sort of "bus". The ssd2858 has two MIPI output ports and can drive multiple panels on them (using virtual channel ids).
We use only one port and one panel so that I will leave this as an excersize to future developers of the ssd driver...
Most urgent is to get the single-panel rotation mode working.
I have a somewhat similar setup on one of my boards (MIPI DPI -> encoder -> DSI panel), which has the same issue, but I haven't yet started to work on it.
Yes, that would be almost the same concept.
But then trouble starts: the boot process hangs after creating the X11 socket and I have not found a way to debug this. Some LEDs are (software) blinking but I can't login: through the console at this stage.
startx hasn't even been called (I had removed it), so that it is a misleading symptom. I have a guess that it is the text console which tries to initialize let's say a (0 x 0) text terminal or something and then hangs it in a way that it also blocks normal getty initialization. But it is only a guess which might be wrong. The last kernel log activity is:
Are you using omapdrm? If so, you can disable fbconsole and maybe fbdev.
fbdev eas already disabled but disabling fbconsole was a miracle :)
That will help in the case that fbconsole has console lock taken when a crash happens (and nothing is printed).
Now I could almost every time boot to a "login:" prompt.
Except for NULL pointer dereferencing (I had forgotten to implement one of the dsi_ops called by the panel driver).
So it appears that if such a panic occurs while the fbconsole is being set up there is no console UART available due to locking.
[ 8.423807] dsi: ssd2858_probe ok [ 8.512172] [drm] Initialized drm 1.1.0 20060810 [ 8.803653] driver_register 'btl507212-w677l' [ 8.809926] dsi: w677l_probe() [ 8.813136] dsi: w677l_probe_of() [ 8.817784] dsi: w677l_probe ok [ 9.232203] driver_register 'omapdrm' [ 9.240322] omap_connect_dssdevs [ 9.243754] omap_connect_dssdevs: hdmi [ 9.252127] dss_mgr_connect 1 hdmi.0 [ 9.256846] omap_connect_dssdevs: lcd [ 9.262098] dsi: w677l_connect() [ 9.265544] dsi: ssd2858: ssd2858_connect [ 9.269942] dsi_connect /dsi.0 -> /dsi.0 [ 9.277707] dss_mgr_connect 0 dsi.0 [ 9.283323] dsi: ssd2858: ssd2858_request_vc [ 9.288012] dsi: ssd2858: ssd2858_request_vc assigned channel 0 [ 9.294275] dsi: ssd2858: ssd2858_set_vc_id [ 9.299807] dsi: ssd2858: ssd2858_request_vc [ 9.304321] dsi: ssd2858: ssd2858_request_vc assigned channel 1 [ 9.311670] dsi: ssd2858: ssd2858_set_vc_id [ 9.317264] dsi: w677l_connect() ok [ 9.320957] omap_connect_dssdevs done !no_displays [ 9.356554] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). [ 9.365465] [drm] No driver support for vblank timestamp query. [ 9.373257] dsi: w677l_disable() [ 9.378238] [CONNECTOR:26:HDMI-A-1] [ 9.381943] [CONNECTOR:30:Unknown-1] [ 9.387303] omap_connector_mode_valid() [ 9.391366] check_timings() [ 9.394332] dsi: w677l_check_timings() [ 9.399032] [CONNECTOR:30:Unknown-1] probed modes : [ 9.404196] Modeline 35:"720x1280" 60 76723 720 725 730 888 1280 1330 1390 1440 0x48 0xa [ 9.464559] [drm] Enabling DMM ywrap scrolling
(includes some debug logging I have added through omapdss).
What I never see is that the panel (or ssd) gets an enable() call, unless I disable the ssd chip in device tree in which case the panel is enabled and works.
So something hangs between panel connect and panel enable if my encoder driver is included in the pipeline.
I understand that things work as follows:
- both drivers are probed
- both drivers register themselves with the omapdss system
- only the panel driver receives a connect() because it has a display alias
- it should trigger the encoder driver to connect() to the omap
- and the panel receives a check_timings()
- later on the panel should receive an enable() which also should enable the panel and be forwarded to the encoder
- the encoder enables and programs the registers
Yes, all the above are true.
Fine!
What is also not exactly clear to me is the relation between the in->ops.dsi->something() and in->driver.something().
Yes, it's "interesting". Legacy stuff, etc. =).
in->driver.something is what the driver at the end of the display chain offers. I.e. panel or a connector. It has operations which are not exactly related to any display bus, but more to the whole pipeline. These are called by the omapdrm or omapfb when they want to e.g. enable a display.
Ok. This means they are called only for the end of the pipeline, i.e. the panel, because it has a display alias?
Would explain why it is not called for my man-in-the-middle.
in->ops.dsi->something is what a driver inside the the video pipeline offers, specific to the bus in question. DSS's DSI and the ssd2858 have DSI outputs, so both of them should offer dsi ops. A DSI peripheral (in your case, ssd2858 and the panel) can use the dsi ops to do DSI operations.
Ok, that is fine.
And how the timing parameters are to be initialized correctly. There are 3 (?) locations where I have to define them. One before registration in the probe() method, then in the dsi_config and the last is get_timings().
This also raises the question how we can properly initialize the timings data that the ssd2858 driver reports to the omap during omapdss_register_output().
The problem is that we have to calculate the proper timings based on the panel timings. But at this stage of driver set up we do not know the panel through dssdev->dst() and hence can't ask it for its timings. And it has not even been probed.
Not initializing dssdev->panel.timings before omapdss_register_output and assuming that get_timings() is called later on (is it ever called???) leads to strange effects.
Yes, there might be issues there. I've noticed something odd there too. In your case, I guess you can just use fixed timings in the panel and ssd drivers to get forward?
For a quick hack, yes. I can just copy the panel timings statically into the ssd driver. And do the timings calculations once during probe.
A better solution that really asks the panel driver at the right moment - or postpones omapdss_register_output() until the panel asks for enable() - can be developed later.
This appears to start to work (thanks to your proposal to disable fbconsole for debugging):
[ 17.818046] [CONNECTOR:30:Unknown-1] [ 17.821929] omap_connector_mode_valid() [ 17.826044] check_timings() [ 17.829072] dsi: w677l_check_timings() [ 17.833109] [CONNECTOR:30:Unknown-1] probed modes : [ 17.838343] Modeline 35:"720x1280" 60 76723 720 725 730 888 1280 1330 1390 1440 0x48 0xa [ 17.849178] omap_encoder_update() [ 17.852703] check_timings() [ 17.855708] dsi: w677l_check_timings() [ 17.859771] omap_encoder_enable()dsi: w677l_enable() [ 17.865079] dsi: w677l_start() [ 17.868773] dsi: ssd2858: ssd2858_bus_lock [ 17.873152] dsi: w677l_power_on() [ 17.876749] dsi: w677l_reset(0) [ 17.880284] dsi: ssd2858: ssd2858_set_config [ 17.884823] dsi_set_config [ 17.888198] dss_pll_calc clkin=19200000 min=4294955296 max=912000000 [ 17.894965] hp clkdco=1800000000 min=150000 max=52000000 [ 17.918742] omapdss DSI error: failed to find suitable DSI clock settings [ 17.925962] dsi: ssd2858: ssd2858_enable [ 18.436902] omapdss PLL error: cannot lock DSS DPLL [ 18.442173] omapdss DSI error: Failed to set dsi clocks [ 18.449386] btl507212-w677l 58004000.encoder:lcd: failed to enable DSI [ 18.456367] dsi: ssd2858: ssd2858_bus_unlock [ 18.460895] btl507212-w677l 58004000.encoder:lcd: enable failed [ 18.467220] omapdrm omapdrm.0: Failed to enable display 'lcd': -5
So I have advanced the code to a point where it tries to set up the OMAP5 video output. Now I have to find out what is wrong with the timing values passed to the dss driver so that it does not find clock settings.
I have fixed the timing calculation and passing issues (pixelclock wasn't set properly and dss min/max clock without range) and can now write DCS commands to the panel and read back (in hardware bypass mode). This means that the kernel code flow is starting to do useful things.
As soon as I have fixed that, I hope that I just have to make DCS/MCS command messages work to program panel and ssd chip (which is a little tricky because panel commands must go through the ssd which has to be switched to a bypass mode)...
It now sounds reasonable to fix initializing the ssd2858 tomorrow and then we may have a much better panel driver in our kernel.
BR, NIkolaus